python:getattr的协作超级调用__
我正在使用与此代码类似的东西:python:getattr的协作超级调用__,python,super,getattr,getattribute,Python,Super,Getattr,Getattribute,我正在使用与此代码类似的东西: class BaseClass(object): def __getattr__(self, attr): return lambda:'1' class SubClass(BaseClass): def foo(self): suffix = '2' return super(SubClass, self).foo() + suffix class SubClass2(SubClass):
class BaseClass(object):
def __getattr__(self, attr):
return lambda:'1'
class SubClass(BaseClass):
def foo(self):
suffix = '2'
return super(SubClass, self).foo() + suffix
class SubClass2(SubClass):
def foo(self):
suffix = '3'
return super(SubClass2, self).foo() + suffix
o = SubClass2()
print o.foo()
我希望看到“123”的输出,但我得到了一个错误AttributeError:“super”对象没有属性“foo”
。Python甚至没有尝试使用基类的\uu getattr\uu
如果不修改基类并保持两个超级调用的相似性,我将无法获得所需的输出。这里有适合我的合作超级球模式吗
我知道super()以某种方式重写了getattr,以完成它需要做的事情,但我想问的是,是否有任何合理的解决方法,允许在适当的时候调用子类的
\uuu getattr\uuu
。这似乎工作正常。我现在不明白为什么标准的超级类不这么做
class super2(super):
def __getattr__(self, attr):
return self.__self__.__getattr__(attr)
class BaseClass(object):
def __getattr__(self, attr):
return lambda:'1'
class SubClass(BaseClass):
def foo(self):
suffix = '2'
return super2(SubClass, self).foo() + suffix
class SubClass2(SubClass):
def foo(self):
suffix = '3'
return super2(SubClass2, self).foo() + suffix
o = SubClass2()
print o.foo()
啊,这是一个很好的问题 简言之,这里发生的事情是CPython内部偶尔需要 在进行属性查找时使用快捷方式,这种情况令人惊讶 行为是后果之一(另一个后果是提高绩效) 为了准确了解这种情况下发生了什么,我们需要冒险 在
super
的定义中:
请特别注意,它没有定义
(又名\uuuuu getattr\uuuuu
),但确实定义了(又名\uuuuuuu getattribute\uuuuu
):
(回想一下,每次调用属性时都会调用\uuuu getattribute\uuuu
)
请求,而不是\uuu getattr\uuuu
,仅当属性
对象上不存在(大致:如果属性不在对象的
\uuuu dict\uuuu
))
接下来,研究
(akasuper.\uuuu getattribute\uuuu
),我们可以看到实现是
大约:
@eevee的可能副本拟议的副本询问“为什么超级不工作?”而我要求的是一个可行的过程,因为超级不工作。请注意
object.\uuuu getattr\uuuu
不存在,因此这将打破object
已经脆弱的钻石继承案例。在某些情况下,这也可能允许元类方法干扰方法解析。应检查第3行的hasattr(self.\uuuuuself.\uuuuuuuuuuuuu getattr.'uuuuuuuuuuuuuuu')
,如果未提供\uuuuuuuuu getattr.
,则引发异常。
PyTypeObject PySuper_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"super", /* tp_name */
...
0, /* tp_getattr */
...
super_getattro, /* tp_getattro */
...
};
class super(object):
def __init__(self, obj_type, obj):
self.obj_type = obj_type
self.obj = obj
def __getattribute__(self, attr):
i = self.obj_type.__mro__.find(self.obj_type)
i += 1
while i < len(obj_type.__mro__):
cur_type = self.obj_type.__mro__[i]
cur_dict = cur_type.__dict___
res = cur_dict.get(attr)
if res is not None:
return res
i += 1
return object.__getattribute__(self, attr)
$ pypy super.py
Traceback (most recent call last):
File "app_main.py", line 72, in run_toplevel
File "super.py", line 16, in <module>
print o.foo()
File "super.py", line 13, in foo
return super(SubClass2, self).foo() + suffix
File "super.py", line 8, in foo
return super(SubClass, self).foo() + suffix
AttributeError: 'super' object has no attribute 'foo'