关于继承:Python中的super(type)是什么?

what is super(type) in python?

类定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
class A(object):
    def foo(self):
        print"A"


class B(object):
    def foo(self):
        print"B"


class C(A, B):
    def foo(self):
        print"C"

输出:

1
2
3
4
5
6
>>> super(C)
<super: <class 'C'>, NULL>
>>> super(C).foo
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
AttributeError: 'super' object has no attribute 'foo'

什么是使用超(型)如果我们不能访问属性的一类?


super(type)是一个"未绑定"的超对象。Super上的文档讨论了这一点,但并没有详细说明"未绑定"超级对象是什么或做什么。这只是语言的一个事实,你不能以你试图使用它们的方式使用它们。

这也许就是你想要的:

1
2
>>> super(C, C).foo is B.foo
True

也就是说,一个未绑定的超对象有什么好处?我自己也得查一下,在这里找到了一个不错的答案。但是,请注意,本文的结论是unbound super是一种语言缺陷,没有实际用途,应该从语言中删除(我同意阅读本文)。本文对"未绑定超级"的解释始于:

Unbound super objects must be turned into bound objects in order to make them to dispatch properly. That can be done via the descriptor protocol. For instance, I can convert super(C1) in a super object bound to c1 in this way:

1
2
>>> c1 = C1()
>>> boundsuper = super(C1).__get__(c1, C1) # this is the same as super(C1, c1)

所以,这似乎没什么用,但文章继续说:

Having established that the unbound syntax does not return unbound methods one might ask what its purpose is. The answer is that super(C) is intended to be used as an attribute in other classes. Then the descriptor magic will automatically convert the unbound syntax in the bound syntax. For instance:

1
2
3
4
5
6
7
8
9
>>> class B(object):
...     a = 1
>>> class C(B):
...     pass
>>> class D(C):
...     sup = super(C)
>>> d = D()
>>> d.sup.a
1

This works since d.sup.a calls super(C).__get__(d,D).a which is turned into super(C, d).a and retrieves B.a.

There is a single use case for the single argument syntax of super that I am aware of, but I think it gives more troubles than advantages. The use case is the implementation of autosuper made by Guido on his essay about new-style classes.

The idea there is to use the unbound super objects as private attributes. For instance, in our example, we could define the private attribute __sup in the class C as the unbound super object super(C):

1
>>> C._C__sup = super(C)

但是请注意,本文继续描述这方面的问题(它并不完全正确,我认为主要是由于MRO依赖于您所处理的实例的类,因此给定一个实例,根据给定的X实例,某些X类的超类可能会有所不同)。


要完成你想要的,你需要这样称呼它:

1
2
3
>>> myC = C()
>>> super(C,myC).foo()
A


注意,有一个NULL引用了一些对象。它基本上需要一个类和一个相关对象的实例才能运行。

1
2
>>> super(C, C()).foo
<bound method C.foo of <__main__.C object at 0x225dc50>>

有关更多详细信息,请参阅:使用uu init_uu()方法了解python super()。