jte*_*ace 9 python inheritance python-2.x class-method python-3.x
这按预期工作:
>>> class Foo(object):
... @classmethod
... def hello(cls):
... print 'hello, foo'
...
>>> class Bar(Foo):
... @classmethod
... def hello(cls):
... print 'hello, bar'
... super(Bar, cls).hello()
...
>>> b = Bar()
>>> b.hello()
hello, bar
hello, foo
Run Code Online (Sandbox Code Playgroud)
我也可以显式调用基类:
>>> class Bar(Foo):
... @classmethod
... def hello(cls):
... print 'hello, bar'
... Foo.hello()
...
>>> b = Bar()
>>> b.hello()
hello, bar
hello, foo
Run Code Online (Sandbox Code Playgroud)
我想知道为什么我不能省略第一个参数super,像这样:
>>> class Bar(Foo):
... @classmethod
... def hello(cls):
... print 'hello, bar'
... super(Bar).hello()
...
>>> b = Bar()
>>> b.hello()
hello, bar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in hello
AttributeError: 'super' object has no attribute 'hello'
Run Code Online (Sandbox Code Playgroud)
当super没有第二个参数的调用结果似乎是超类型中的类类型时:
>>> class Bar(Foo):
... @classmethod
... def hello(cls):
... print Foo, type(Foo)
... print super(Bar), type(super(Bar))
... print cls, type(cls)
...
>>> b = Bar()
>>> b.hello()
<class '__main__.Foo'> <type 'type'>
<super: <class 'Bar'>, NULL> <type 'super'>
<class '__main__.Bar'> <type 'type'>
Run Code Online (Sandbox Code Playgroud)
我想我只是想知道这里的设计.为什么我需要将类对象传递给超级调用以获取对基类类型的引用Foo?对于普通方法,传递self给函数是有意义的,因为它需要将基类类型绑定到类的实际实例.但是类方法不需要类的特定实例.
编辑:我在Python 3.2中得到的错误与上面2.7中的错误相同super(Bar).hello().但是,我可以做到super().hello(),而且工作正常.
Mar*_*ers 12
super()返回一个描述符,需要两个项目:
对于两个参数(和隐式零参数*)的情况,第二个参数用于绑定,但如果不传入第二个参数,super()则无法调用描述符协议来绑定返回的函数,类方法,属性或其他描述符.classmethods仍然是描述符并受到约束; 绑定到类而不是实例,但super() 不知道描述符将如何使用绑定的上下文.
super()不应该也不能知道你正在查找类方法而不是常规方法; 类方法仅与常规方法不同,因为它们的.__get__()方法行为不同.
为什么类方法绑定?因为当你继承Foo但不重写时.hello(),调用Bar.hello()调用Foo.__dict__['hello']函数,将它绑定到Bar,你的第一个参数hello(cls)将是那个子类,而不是Foo.
如果没有第二个参数,则super()返回一个可以在以后手动绑定的未绑定对象.您可以使用实例.__get__()提供的方法自行进行绑定super():
class Bar(Foo):
@classmethod
def hello(cls):
print 'hello, bar'
super(Bar).__get__(cls, None).hello()
Run Code Online (Sandbox Code Playgroud)
super().__get__()在没有上下文的实例上有效地返回具有上下文集的新super()实例.在具有上下文的实例上.__get__()返回self; 它已经受到约束.
*在Python 3中,super()在绑定方法内部不带参数调用将使用调用框架隐式地发现类型和绑定对象是什么,因此在这种情况下您不再需要显式传入类型和对象参数.Python 3实际上__class__为此目的向方法添加了一个隐式闭包变量.请参阅PEP 3135和为什么Python 3.x的超级()魔术?