一、属性的几种访问方式

1、类.属性名

>>> class C:
def __init__(self):
self.x = 'X-man' >>> c = C()
>>> c.x
'X-man'

2、用内置函数getattr()访问属性

>>> getattr(c,'x','莫有这个属性')
'X-man'
>>> getattr(c,'y','莫有这个属性')
'莫有这个属性'
>>>

3、用property方法访问属性

class C:
def __init__(self,size=10):
self.size=size def getsize(self):
return self.size def setsize(self,value):
self.size = value def delsize(self):
del self.size x=property(getsize,setsize,delsize) 执行结果:
>>> c = C()
>>> c.x
10
>>> c.x=1
>>> c
<__main__.C object at 0x10c012f60>
>>> c.x
1
>>> del c.x
>>> c.x
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
c.x
File "/Users/wufq/Desktop/property.py", line 6, in getsize
return self.size
AttributeError: 'C' object has no attribute 'size'

4、各类内置函数访问属性

*  __getattr__(self,name)

定义当用户试图获取一个不存在的属性时的行为

* __getattribute__(self,name)

定义当该类的属性被访问时的行为

* __setattr__(self,name,value)

定义当一个属性被设置时的行为

* __delattr__(self,name)

定义当一个属性被删除时的行为

class C:
def __getattr__(self,nane):
print("__getattr__") def __getattribute__(self,name):
print("__getattribute__")
return super().__getattribute__(name) def __setattr__(self,name,value):
print("__setattr__")
super().__setattr__(name,value) def __delattr__(self,name):
print("__delattr__")
super().__delattr__(name) >>> c = C()
>>> c.x
__getattribute__
__getattr__
>>> c.x =
__setattr__
>>> c.x
__getattribute__ >>> del c.x
__delattr__
>>> c.x '''
代码解析:
|--1、由第一个c.x先后打印出来__getattribute__和__getattr__,可以看出来,程序先找__getattribute__(定义当该类的属性被访问时的行为),然后
|-- 在找__getattr__(属性不存在时的访问行为)
|--2、由c.x =1 打印出来__setattr__,可以得知,当属性被设置时调用的是此方法
|--3、由del c.x=1 打印出来__delattr__可以得知,当属性被删除时调用此方法
'''

5、写一个矩形类,默认有宽和高两个属性

如果为一个叫square的属性赋值,那么说明这是一个正方形,值就是正方形的边长,此时宽和高都应该等于边长

class Rectangle:
def __init__(self,width=0,height=0):
self.width = width
self.height = height
#用square这个属性来标记正方形
def __setattr__(self,name,):
if name == 'square':
self.width = value
self.height = value
else:
self.name = value def getArea(self):
return self.width * self.height >>> r1 = Rectangle(4,5)
Traceback (most recent call last):
  File "<pyshell#15>", line 1, in <module>
    r1 = Rectangle(4,5)
  File "/Users/wufq/Desktop/正方形.py", line 4, in __init__
    self.width = width
  File "/Users/wufq/Desktop/正方形.py", line 12, in __setattr__
    self.name = value
  File "/Users/wufq/Desktop/正方形.py", line 12, in __setattr__
    self.name = value
  File "/Users/wufq/Desktop/正方形.py", line 12, in __setattr__
    self.name = value
  [Previous line repeated 987 more times]
  File "/Users/wufq/Desktop/正方形.py", line 8, in __setattr__
    if name == 'square':
RecursionError: maximum recursion depth exceeded in comparison '''
代码解析:
|-- 为什么会报错:原因:首先实例化对象时给width和height赋值,赋值时就调用了__setattr__方法
|-- 进入__setattr__方法,会首先判断name有没有等于square,明显此时没有,则执行else里面的语句
|-- self.name = value,则又一次循环调用默认的__init__方法,依次这样就会进入死循环
'''

改进的方法

#第一种方法:采用super()方法调用基类
#第二种方法:采用字典的方法,__dict__ class Rectangle:
def __init__(self,width=0,height=0):
self.width = width
self.height = height
#用square这个属性来标记正方形
def __setattr__(self,name,value):
if name == 'square':
self.width = value
self.height = value
else:
#self.name = value
#super().__setattr__(name,value)
self.__dict__[name]=value #采用__dict__方法的原因是:给属性square所赋值存储到dict字典内 def getArea(self):
return self.width * self.height
执行结果:
>>> r1 = Rectangle(4,5)
>>> r1.getArea()
20
>>> r1.square = 10
>>> r1.getArea()
100
>>> r1.__dict__
{'width': 10, 'height': 10}

二、练习题

1、对象的属性发生赋值操作时,将实际的的值+1赋值给相应的属性。

def __setattr__(self,name,value):
self.name = value + 1 错误原因:属性被赋值时,__setattr__()会被调用,而里边的self.name = value +1又会再次触发__setattr__()调用,导致无限递归(死循环)

正确的写法

class C:
def __init__(self,name):
self.name = name
def __setattr__(self,name,value): self.__dict__[name]=value+1
print("name=",self.__dict__[name],"value=",value) 执行结果:
>>> c = C(2)
name= 3 value= 2

2、自定义该类的属性被访问的行为,你应该重写那个魔法方法

答:__getattribute__(self,name)  :属性被访问时调用这个方法

3、当访问一个不存在的属性时,不报错且提示“该属性不存在”

class Demo:
def __getattr__(self,name):
return "该属性不存在" 执行结果:
>>> demo = Demo()
>>> demo.x
'该属性不存在'
>>>

4、编写一个Demo类,使的下边代码可以正常执行

class Demo:
def __getattr__(self,name):
self.name = 'FishC'
return self.name
def __getattribute__(self,name):
return super().__getattribute__(name)
def __setattr__(self,name,value):
return super().__setattr__(name,value) 执行结果:
>>> d=Demo()
>>> d.x
'FishC'
>>> d.x = "X-man"
>>> d.x
'X-man'
>>>

5、编写一个Counter类,用于实时检查对象有多少个属性

#需求:检测对象有多少个属性
class Counter:
def __init__(self):
super().__setattr__('counter',0)
def __setattr__(self,name,value):
super().__setattr__('counter',self.counter + 1)
super().__setattr__(name,value)
def __delattr__(self,name):
super().__setattr__('counter',self.counter - 1)
super().__delattr__(name) 执行结果:
>>> c = Counter()
>>> c.x=1
>>> c.counter
1
>>> c.y =2
>>> c.z = 3
>>> c.m =4
>>> c.counter
4
>>> del c.m
>>> c.counter
3
>>>

【Python045-魔法方法:属性访问】的更多相关文章

  1. python魔法方法-属性访问控制

    属性访问控制 所谓的属性访问控制就是控制点号访问属性的行为,而且不仅是类的外部,连类的内部也受控制,代码见真章,边看代码边解释: __getattr__(self, item) 定义当访问不存在的属性 ...

  2. Python魔法方法之属性访问 ( __getattr__, __getattribute__, __setattr__, __delattr__ )

    通常情况下,我们在访问类或者实例对象的时候,会牵扯到一些属性访问的魔法方法,主要包括: ① __getattr__(self, name): 访问不存在的属性时调用 ② __getattribute_ ...

  3. python_魔法方法(四):属性访问

    通常可以通过点(.)操作符的形式去访问对象的属性,也可以通过BIF适当地去访问属性,看个例子吧 >>> class A(): def __init__(self): self.x = ...

  4. Python类属性访问的魔法方法

    Python类属性访问的魔法方法: 1. __getattr__(self, name)- 定义当用户试图获取一个不存在的属性时的行为 2. __getattribute__(self, name)- ...

  5. 《Python基础教程(第二版)》学习笔记 -> 第九章 魔法方法、属性和迭代器

    准备工作 >>> class NewStyle(object): more_code_here >>> class OldStyle: more_code_here ...

  6. python学习笔记之七:魔法方法,属性

    在python中,有的名称会在前面和后面加上两个下划线,由这些名字组成的集合所包含的方法称为魔法方法(或者是特殊方法).如果对象实现了这些方法中的某一个,那么这个方法会在特殊的情况下(确切地说是根据名 ...

  7. Python笔记(二十六)_魔法方法_属性的魔法方法

    属性的魔法方法 __getattribute__(self,name):当该类的属性被访问时,自动触发,是最先被触发的属性方法 __setattr__(self,name,value):当一个属性被设 ...

  8. 【python学习笔记】9.魔法方法、属性和迭代器

    [python学习笔记]9.魔法方法.属性和迭代器 魔法方法:xx, 收尾各有两个下划线的方法 __init__(self): 构造方法,创建对象时候自动执行,可以为其增加参数, 父类构造方法不会被自 ...

  9. Solidity属性和方法的访问权限

    属性:默认是internal的类型,外部是不可以访问调用的,如果加上public的话,那么是会自动为这个属性加上一个get的方法的,比如uint   public _age; => functi ...

随机推荐

  1. 多么痛的领悟---关于RMB数据类型导致的元转分分转元的bug

    关于金额的数据类型,以及元转分分转元之间这种转换,以及元和分的比较,我相信很多人都踩过坑. 反正我是踩过. 而且,昨天和今天又重重的踩了两脚. 代付查询接口,支付中心给溢+响应的报文里,amount的 ...

  2. Unity3d vector3.forward和transform.forward的区别!

    原文连接: http://blog.csdn.net/kaluluosi111/article/details/17206655 在unity3d中有2个forward,一个是vector3.forw ...

  3. webpack的使用一

    1.为什么使用webpack 模块化,让我们可以把复杂的程序细化为小的文件; 类似于TypeScript这种在JavaScript基础上拓展的开发语言:使我们能够实现目前版本的JavaScript不能 ...

  4. can not create symbolic link HDFS解压自动配置lib报错。

    如题,使用FusionInsight解压生成样例代码的时候报错,找不到解释.只猜测是权限问题.然后并没有仔细静心思考,心里杂念很多,很浮躁. 解决方法是“以管理员身份运行“. 想想高中:面对问题,不能 ...

  5. Django中的View视图讲解

    Django中的View视图(view.py)是负责处理用户请求和返回响应的逻辑. 视图函数或视图简而言之就是一个python函数,它接受一个web请求并返回一个Web响应. 此响应可以是网页的HTM ...

  6. 关于oracle中的数字类型

    1.关于number类型. 以下是从其文档中摘录出的一句话: p is the precision, or the total number of significant decimal digits ...

  7. Rpgmakermv(25) 游戏数据

    随着对RMMV插件了解的深入,我们会发现如果我们想要对游戏数据进行一些扩展,首先要了解游戏数据,游戏数据在官方代码中的rpg_managers.js里,这一节我们将要对这个官方类有一些基础的了解,并且 ...

  8. IIS7配置rewriter

    遇到的问题就是rewriter不起效果冲IIS6迁移过来的.最后发现是Framework 4.0的原因!记录处理方式为: 一. <configSections> <section n ...

  9. JavaScript(四):运算符&数据类型转换

    +:算符的加法:连接字符串 加法会将其它类型的值,自动转为字符串,然后再进行连接运算! var a=1+2; console.log('first: '+a); var a=1+2+'3';//先计算 ...

  10. sitecore系列教程之简单和个性化

    现代Web开发倾向于关注内容管理系统(CMS)的功能丰富的程序.最终用户可以做什么?作为内容管理者,我们可以为最终用户实现其目标提供哪些功能?开发人员可以为内容管理员构建哪些组件来实现它们? 相关内容 ...