Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.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 避免uu getattribute中的无限循环___Python_Python 3.x - Fatal编程技术网

Python 避免uu getattribute中的无限循环__

Python 避免uu getattribute中的无限循环__,python,python-3.x,Python,Python 3.x,方法\uuuu getattribute\uuuu需要仔细编写,以避免无限循环。例如: class A: def __init__(self): self.x = 100 def __getattribute__(self, x): return self.x >>> a = A() >>> a.x # infinite looop RuntimeError: maximum recursion dep

方法
\uuuu getattribute\uuuu
需要仔细编写,以避免无限循环。例如:

class A:
    def __init__(self):
        self.x = 100

    def __getattribute__(self, x):
        return self.x

>>> a = A()
>>> a.x    # infinite looop
RuntimeError: maximum recursion depth exceeded while calling a Python object


class B:
    def __init__(self):
        self.x = 100

    def __getattribute__(self, x):
        return self.__dict__[x]

>>> b = B()
>>> b.x    # infinite looop
RuntimeError: maximum recursion depth exceeded while calling a Python object
因此,我们需要以这种方式编写方法:

class C:
    def __init__(self):
        self.x = 100

    def __getattribute__(self, x):
        # 1. error
        # AttributeError: type object 'object' has no attribute '__getattr__'
        # return object.__getattr__(self, x)
        
        # 2. works
        return object.__getattribute__(self, x)
        
        # 3. works too
        # return super().__getattribute__(x)
我的问题是为什么
object.\uuuu getattribute\uuu
方法有效?
object
从哪里获取
\uuuu getattribute\uuuu
方法?如果
对象
没有任何
\uuuu getattribute\uuuu
,那么我们只是在类
C
上调用相同的方法,但是通过超类调用。为什么,那么通过超类调用该方法不会导致无限循环?

执行此操作时:

    return object.__getattribute__(self, x)
    return self.x
您正在调用一个特定的函数——在对象类中定义的函数,而不是在中定义的函数,因此不存在递归

执行此操作时:

    return object.__getattribute__(self, x)
    return self.x

你让python选择调用哪个函数,它从A调用这个函数,你有一个无限递归。

你似乎觉得你的
\uuuu getattribute\uuuu
实现只是一个钩子,如果你提供它,python会调用它,否则,解释器将直接执行其正常功能

这是不对的。当python在实例上查找属性时,
\uuu getattribute\uuu
是所有属性访问的主要条目,而
object
提供默认实现。因此,您的实现将覆盖原始实现,如果您的实现没有提供返回属性的替代方法,那么它将失败。您不能在该方法中使用属性访问,因为对实例(
self
)的所有属性访问都是通过
类型(self)进行的

解决此问题的最佳方法是再次调用重写的原始文件。这就是
super(C,self).\uu getattribute\uuu(attr)
的作用;您正在请求类解析中的下一个类为您处理属性访问

或者,您可以直接调用unbound
对象。此方法的C实现是属性访问的最后一站(它可以直接访问
\uuuuu dict\uuuu
,因此不受相同限制)

请注意,
super()
返回一个代理对象,该对象将查找下一步在方法解析有序基类中可以找到的任何方法。如果不存在这样的方法,它将因属性错误而失败。它永远不会调用原始方法。因此
Foo.bar()
查找
super(Foo,self).bar
将是基类实现或属性错误,而不是
Foo.bar
本身。

这样写(C继承自对象):


现在您明白了为什么object.\uuuuGetAttribute\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但即使我没有,我仍然想知道为什么会这样的全部细节。好吧,要么你必须拦截所有属性访问,要么你不:-)@MartijnPieters——我同意。我的主要困惑是为什么从
对象
调用相同的方法不会导致无限递归。为什么说“对象没有任何
\uu getattribute\uuu
”<代码>a=对象();dir(a)
您将看到它被列出……在
对象
类上没有定义这样的函数。如果在那里定义了一个函数,那么
对象
也将定义
\uuu getattr\uuu
(正如#1错误所示,它没有定义)。那么,为什么object只定义
\uuuu getattribute\uuuu
方法呢?@greengit:为什么不呢?当我访问
对象时,我看到
。\uuuuu getattribute\uuuu
。所以你是说
对象
只定义
\uu getattribte\uuuuu
,而不是
\uu getattr\uuuuuu
?据我所知,
object
类对所有这些方法的实现都是不可操作的。如果我在某个地方出错,请纠正我。@greengit:Nope,
object.\uu getattribute\uuu
是对象属性访问的主要访问点。当您在子类上定义它时,您正在重写它,并且为了再次获得正常的行为,您需要调用被重写的实现。“我以为对象没有op实现”?到底为什么。。。?如果根对象对特殊方法的实现没有ops,那么事情怎么办?当您编写自己的时,您将覆盖什么?如果基本方法不做任何事情,这些重写将如何访问基本功能?这根本没有道理。