小甲鱼python045魔法方法:属性访问
0 总结
0.0 属性访问方法
- object.attr
- getattr()
[ ] 内为可选项,如果不添加该项,且如果attr不存在于object中则报错AttributeErrorgetattr(object, 'attr'[, 'return this string if attr is not in object'])
0.1 property函数
用属性访问属性
class C:
def __init__(self, size = 10):
self.size = size
def getSize(self):
return self.size
def setSize(self, size):
self.size = size
def delSize(self):
del self.size
x = property(getSize,setSize,delSize)
>>> c = C()
>>> c.x = 1
>>> c.x
1
>>> c.size
1
>>> del c.x
>>> c.size
AttributeError: 'C' object has no attribute 'size'
使用了property()函数是 x 和 size挂钩
0.2 几种魔法方法访问属性
重写魔法方法控制属性访问
魔法方法 | 功能 |
---|---|
__getattr__(self, name) | 定义当用户试图获取一个不存在的属性时的行为 |
__getattribute__(self, name) | 定义当该类属性被访问时的行为,无论该属性是否存在 |
__setattr__(self,name, value) | 定义当一个属性被设置时的行为 |
__delattr__(self, name) | 定义当一个属性被删除时的行为 |
对这些进行修改
class C:
def __getattribute__(self, name):
print("getattribute")
return super().__getattribute__(name)
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
注意__setattr__()的无限递归:
>>> class Rectangle():
def __init__(self, height=0, width=0):
self.height = height
self.width = width
def __setattr__(self, name, value):
if name == "square":
self.height = value
self.width = value
else:
self.name = value
>>> r = Rectangle()
Traceback (most recent call last):
File "<pyshell#42>", line 1, in <module>
r = Rectangle()
File "<pyshell#41>", line 3, in __init__
self.height = height
File "<pyshell#41>", line 10, in __setattr__
self.name = value
File "<pyshell#41>", line 10, in __setattr__
self.name = value
File "<pyshell#41>", line 10, in __setattr__
self.name = value
[Previous line repeated 325 more times]
File "<pyshell#41>", line 6, in __setattr__
if name == "square":
RecursionError: maximum recursion depth exceeded in comparison
#解决递归方法1: 使用基类
def __setattr__(self, name, value):
if name == "square":
self.height = value
self.width = value
else:
super().__setattr__('name',value)
#解决递归方法2: 使用__dict__属性
def __setattr__(self, name, value):
if name == "square":
self.height = value
self.width = value
else:
self.__dict__['name'] = value