笔记
属性访问
1.__getattr__(self,name)
定义当用户试图获取一个不存在的属性时的行为
2.__getattribute__(self,name)
定义当该类的属性被访问时的行为。并返回该属性的值。
3.__setattr__(selff,name,value)
定义当一个属性被设置时的行为
4.__delattr__(self,name)
定义当一个属性被删除时的行为
注:object类没有__getattr__方法。
演示例:
class C:
def __getattribute__(self,name):
print('getattribute')
return super().__getattribute__(name) #使用super可以省略self
def __getattr__(self,name):
print('getattr')
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 = 1
setattr
>>> c.x
getattribute
1
>>> del c.x
delattr
通过利用print进行检测,我们可以得到如下结论:
访问属性时,先调用getattribute,如果访问不到该属性,再调用getattr
死循环陷阱
演示例:
class Rectangle:
def __init__(self,width = 0,height = 0):
self.width = width
self.height = height
def __setattr__(self,name,value):
if name == 'squre':
self.width = value
self.height = value
else:
self.name = value
def getArea(self):
return self.width * self.height
上述代码乍一看没有问题。但运行时会报错,无限调用__setattr__方法。有两种修改方法:
1.调用基类的魔法方法(推荐)
class Rectangle:
def __init__(self,width = 0,height = 0):
self.width = width
self.height = height
def __setattr__(self,name,value):
if name == 'square':
self.width = value
self.height = value
else:
super().__setattr__(name,value)
def getArea(self):
return self.width * self.height
运行结果如下,一切正常:
#测试长方形
>>> r1 = Rectangle(4,5)
>>> r1.width
4
>>> r1.height
5
>>> r1.getArea()
20
#测试正方形
>>> r1.square = 10
>>> r1.width
10
>>> r1.height
10
>>> r1.getArea()
100
2.利用对象的特殊属性__dict__
调用后返回一个字典,显示属性以及对应的值。
>>>r1.__dict__
{'width':10,'height':10}
那么就可以把super().__setattr__(name,value) 改成 self.__dict__[name] = value