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
))

接下来,研究 (aka
super.\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'