python __getattr__, __setattr__ 和 __getattribute__
获取和设置对象相关属性时常用的三个魔法方法
__getattr__(self, item)
在访问对象的 item 属性且 item 属性不存在时会调用此方法,如果对象已经有 item 这个属性了,则不会调用这个方法,会直接返回对象的 item 属性
__setattr__(self, item, value)
在试图为对象的 item 属性赋值的时候会被调用
__getattribute__(self, item)
访问对象的任何属性,不管存不存在,都会调用此方法
特别注意:重写这些方法的时候需要特别小心,很容易引起死递归
下面是一个会引起死递归的示例
class Loop(object):
def __init__(self, data):
self._data = data
def __getattribute__(self, name):
print 'do something'
return self._data[name]
问题的关键在于:在 __getattribute__ 中访问了 _data 属性,而访问 _data 属性同样会被__getattribute__ 方法拦截,这样就造成了无限递归
File "loop.py", line 11, in __getattribute__
return self._data[name]
RuntimeError: maximum recursion depth exceeded while calling a Python object
要想在 __getattribute__ 访问某个属性,正确的做法是从实例的属性字典直接获取 _data 的属性值,以避免无限递归
class RightWay(object):
def __init__(self, data):
self._data = data
def __getattribute__(self, name):
print 'do something'
data = super(RightWay, self).__getattribute__('_data')
return data[name]
同样的,如果要在 __setattr__ 方法中修改对象的属性,也需要通过 super().__setattr__来完成

浙公网安备 33010602011771号