tre*_*der 25 python python-3.x
__getattribute__需要仔细编写该方法以避免无限循环.例如:
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
Run Code Online (Sandbox Code Playgroud)
因此我们需要以这种方式编写方法:
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)
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么object.__getattribute__方法有效?从何处object获取__getattribute__方法?如果object没有__getattribute__,那么我们只是在类上调用相同的方法,C但是通过超类.为什么,然后通过超类调用方法不会导致无限循环?
Mar*_*ers 28
你似乎有这样一种印象,你的执行下__getattribute__仅仅是一个钩,如果你提供给它的Python会调用它,否则解释器将直接完成其正常的魔力.
这是不正确的.当python在实例上查找属性时,__getattribute__是所有属性访问的主条目,并object提供默认实现.因此,您的实现将覆盖原始实现,如果您的实现没有提供返回属性的替代方法,则它将失败.您不能在该方法中使用属性访问,因为对instance(self)的所有属性访问都会再次通过type(self).__getattribute__(self, attr).
解决这个问题的最佳方法是再次调用被覆盖的原件.那是super(C, self).__getattribute__(attr)进来的地方; 您要求类解析顺序中的下一个类为您处理属性访问.
或者,您可以object.__getattribute__()直接调用未绑定的方法.此方法的C实现是属性访问的最终停止(它具有直接访问权限,__dict__因此不受相同限制的约束).
请注意,super()返回一个代理对象,该对象将查找方法分辨率有序基类中接下来可以找到的任何方法.如果不存在这样的方法,它将失败并出现属性错误.它永远不会调用原始方法.因此Foo.bar()查找super(Foo, self).bar将是基类实现或属性错误,从不 Foo.bar自己.
当你这样做:
return object.__getattribute__(self, x)
Run Code Online (Sandbox Code Playgroud)
你正在调用一个特定的函数 - 在对象类中定义的函数,而不是在A中定义的函数,因此没有递归.
当你这样做:
return self.x
Run Code Online (Sandbox Code Playgroud)
你让python选择要调用哪个函数,并从A中调用一个函数,并且你有一个无限递归.
这样写(C继承自object):
class C(object):
def __init__(self):
self.x = 100
def __getattribute__(self, x):
return object.__getattribute__(self, x)
Run Code Online (Sandbox Code Playgroud)
现在您了解object .__ getattribute __(self,x)起作用的原因-您正在调用父对象。
| 归档时间: |
|
| 查看次数: |
9945 次 |
| 最近记录: |