请参阅现有问题的第二个顶部答案:__getattribute__
,其中包括某人建议的代码:
class Count(object):
def __init__(self, mymin, mymax):
self.mymin = mymin
self.mymax = mymax
self.current = None
def __getattr__(self, item):
self.__dict__[item] = 0
return 0
def __getattribute__(self, item):
if item.startswith('cur'):
raise AttributeError
return super(Count, self).__getattribute__(item)
obj1 = Count(1, 10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)
我的问题是:
当我运行代码时,它没有深入到无限递归(以最大递归深度超过结束)。为什么?而且,如果我将代码super(Count, self).__getattribute__(item)
更改为super(object, self).__getattribute__(item)
,它确实会遇到无限循环。怎么又来了?
请用详细的呼叫过程来解释原因。
发布于 2018-10-09 11:24:48
我将尝试通过将self.__dict__[item]
分解为两部分来简化它:
class Count(object):
def __getattr__(self, item):
print('__getattr__:', item)
d = self.__dict__
print('resolved __dict__')
d[item] = 0
return 0
def __getattribute__(self, item):
print('__getattribute__:', item)
if item.startswith('cur'):
raise AttributeError
return super(Count, self).__getattribute__(item)
obj1 = Count()
print(obj1.current)
输出是
__getattribute__: current
__getattr__: current
__getattribute__: __dict__
resolved __dict__
0
现在,如果我们将super(Count, self)
替换为不正确的构造super(object, self)
,则不会打印消息。这是因为__getattribute__
也将屏蔽对__dict__
的访问。但是,super
对象将指向不存在的object
基类,因此我们的__getattribute__
函数总是抛出AttributeError
。
现在,在__getattribute__
失败后,__getattr__
正在被审判.好吧,它不只是将calling`getattribute__`解析为某个值,而是尝试将其作为一个属性来获得--并再次获得__dict__
。所以我们得到了。
....
__getattribute__: __dict__
__getattr__: __dict__
__getattribute__: __dict__
__getattr__: __dict__
__getattribute__: __dict__
__getattr__: __dict__
__getattribute__: __dict__
__getattr__: __dict__
__getattribute__: __dict__
__getattr__: __dict__
Traceback (most recent call last):
File "getattribute.py", line 15, in <module>
print(obj1.current)
File "getattribute.py", line 4, in __getattr__
d = self.__dict__
File "getattribute.py", line 4, in __getattr__
d = self.__dict__
File "getattribute.py", line 4, in __getattr__
d = self.__dict__
[Previous line repeated 328 more times]
File "getattribute.py", line 8, in __getattribute__
print('__getattribute__: ', item)
RecursionError: maximum recursion depth exceeded while calling a Python object
如果您使用setattr(self, item, 0)
而不是查找self.__dict__
,就可以“避免”:
class Count(object):
def __getattr__(self, item):
setattr(self, item, 0)
return 0
def __getattribute__(self, item):
if item.startswith('cur'):
raise AttributeError
return super(object, self).__getattribute__(item)
obj1 = Count()
print(obj1.current)
当然,这样的代码是不正确的--尽管如此,尝试访问任何其他属性都是失败的。
https://stackoverflow.com/questions/52719103
复制相似问题