Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么在_getattribute__中存在无限递归循环风险?_Python - Fatal编程技术网

Python 为什么在_getattribute__中存在无限递归循环风险?

Python 为什么在_getattribute__中存在无限递归循环风险?,python,Python,请参阅现有问题的第二个顶部答案:,其中包括某人建议的代码: 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 retur

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

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)。\uuuuu getattribute\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。又为什么


请用详细的通话过程解释原因

我将尝试通过将
self.\uu dict\uuu[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)
,则不会打印消息。这是因为
\uuuuu getattribute\uuuuuuuuuuuuuuuuu
还将屏蔽对
\uuuuuuuuuu dict\uuuuuuuuuuuu
的访问。但是,
super
对象将指向不存在的
object
的基类,因此我们的
\uuuu getattribute\uuuu
函数将始终抛出
AttributeError

现在,在
\uuuu getattribute\uuuu
失败后,
\uuuuu getattr\uuuuu
正在为其进行尝试。。。好的,它不只是将
\uuuuuu dict\uuuuuu
解析为某个值,而是尝试将其作为一个属性来获取,最后再次调用
\uuuu getattribute\uuuuu
。因此我们得到了

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

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

某种程度上是相关的:不相关的,但在属性查找中更新对象的状态并最终创建新属性是一个非常糟糕的主意(除非您只在受保护的属性中缓存一些值,但这里不是这种情况)“当我运行代码时,它没有运行到无限递归”=>为什么它应该运行?”@Brunodesshuilliers我将行“return super(Count,self)。\uuuuuu getattribute\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu你永远不应该写
super(object,self)
。这永远都不可能是正确的。object
上面没有任何东西。为什么getattribute会屏蔽对dict的访问?我试过你的代码,我以为代码永远不会到达print语句,但它会到达“d=self.\uuuuuuu dict\uu”。我看到你在解释中添加了,我的问题完全解决了,谢谢!似乎“object”没有名为dict的属性,而任何其他类继承了它。当我使用super(Count,self)时,self。dict可以访问,因为dict是类Count的属性。我理解正确吗?还有,你所说的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)