python属性访问
程序员文章站
2022-07-15 22:20:26
...
1. 使用特殊函数__getattribute__,__getattr__,__setattr__,__delattr__
当想要获得(get)属性时,先访问__getattribute__,如果对象不存在该属性,则继续访问__getattr__
当定义或者修改一个属性时,访问__setattr__
当删除一个属性时,访问__delattr__
>>> class C:
def __init__(self,name='zzw'):
self.name = name
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()
setattr
>>> c.name
getattribute
'zzw'
>>> c.x
getattribute
getattr
>>> c.x = 1
setattr
>>> del c.x
delattr
2. 注意一个陷进:定义/修改属性时递归调用自身,从而进入无限循环。
这是因为在__init__中,self.width=width会调用__setattr__方法,name不是‘square’,故执行else语句self.name=value,这还是一条赋值语句,继续调用__setattr__函数。这样调用自身的递归就会运行出错。
>>> 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:
self.name = value
def getArea(self):
return self.width*self.height
>>> r = Rectangle()
Traceback (most recent call last):
File "<pyshell#42>", line 1, in <module>
r = Rectangle()
File "<pyshell#41>", line 3, in __init__
self.width = width
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
解决方法有两个:
第一是把self.name = value这句改为super().__setattr__(name,value),父类的__setattr__函数是封装正确的,运行不会出错
第二是把self.name = value这句改为self.__dict__[name] = value