gpt4 book ai didi

python - 为什么__getattribute__存在无限递归循环风险?

转载 作者:太空宇宙 更新时间:2023-11-04 00:10:17 59 4
gpt4 key购买 nike

引用现有问题的第二个最佳答案:Difference between __getattr__ vs __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),它确实遇到了无限循环。为什么又是?

请说明原因,并附上详细的来电流程。

最佳答案

我将尝试通过将 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__ ...好吧,而不是仅仅将 __dict__ 解析为某个值,它尝试将其作为属性获取 - 并最终再次调用__getattribute__因此我们得到了。

....
__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)

当然,这样的代码不会是正确的——尽管如此,尝试访问任何其他属性都会失败。

关于python - 为什么__getattribute__存在无限递归循环风险?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52719103/

59 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com