首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么__getattribute__中存在无限的递归循环风险?

为什么__getattribute__中存在无限的递归循环风险?
EN

Stack Overflow用户
提问于 2018-10-09 10:43:05
回答 1查看 515关注 0票数 2

请参阅现有问题的第二个顶部答案:__getattribute__,其中包括某人建议的代码:

代码语言:javascript
运行
复制
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),它确实会遇到无限循环。怎么又来了?

请用详细的呼叫过程来解释原因。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-09 11:24:48

我将尝试通过将self.__dict__[item]分解为两部分来简化它:

代码语言:javascript
运行
复制
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)

输出是

代码语言:javascript
运行
复制
__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__。所以我们得到了。

代码语言:javascript
运行
复制
....
__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__,就可以“避免”:

代码语言:javascript
运行
复制
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)

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52719103

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档