Python 为什么classmethod';我们需要第二个论点吗?
这与预期的效果一样:Python 为什么classmethod';我们需要第二个论点吗?,python,python-3.x,inheritance,python-2.x,class-method,Python,Python 3.x,Inheritance,Python 2.x,Class Method,这与预期的效果一样: >>> class Foo(object): ... @classmethod ... def hello(cls): ... print 'hello, foo' ... >>> class Bar(Foo): ... @classmethod ... def hello(cls): ... print 'hello, bar' ... super(Bar, cls).hello() ...
>>> 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
我还可以显式调用基类:
>>> class Bar(Foo):
... @classmethod
... def hello(cls):
... print 'hello, bar'
... Foo.hello()
...
>>> b = Bar()
>>> b.hello()
hello, bar
hello, foo
我想知道为什么不能省略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'
我想我只是想知道这里的设计。为什么我需要将class对象传递到super调用中以获取对基类类型的引用Foo
?对于普通方法,将self
传递给函数是有意义的,因为它需要将基类类型绑定到类的实际实例。但是classmethod不需要类的特定实例
编辑:
在Python3.2中,我得到的错误与上面在2.7中针对super(Bar.hello()
的错误相同。但是,我可以简单地执行super().hello()
,效果很好。super()
返回一个,需要两项:
- 搜索类层次结构的起点
- 绑定返回方法的参数
super()
无法调用描述符协议来绑定返回的函数、类方法、属性或其他描述符classmethods
仍然是描述符,并且是绑定的;绑定到类而不是实例,但是super()
不知道描述符将如何使用绑定到的上下文
super();类方法只与常规方法不同,因为它们的。\uuuu get\uuuu()
方法的行为不同
为什么类方法是绑定的?因为当你子类Foo
但不覆盖.hello()
时,调用Bar.hello()
调用Foo.\uu dict\uuu['hello']
函数,将它绑定到Bar
,而hello(cls)
的第一个参数将是该子类,而不是Foo
如果没有第二个参数,super()
将返回一个未绑定的对象,稍后可以手动绑定该对象。您可以使用由super()
实例提供的get\uu()
方法自己进行绑定:
class Bar(Foo):
@classmethod
def hello(cls):
print 'hello, bar'
super(Bar).__get__(cls, None).hello()
super()。在具有上下文的实例上,只返回self
;它已经绑定了
*在Python3中,从绑定方法内部调用不带参数的super()
,将使用调用框架隐式地发现类型和绑定对象,因此在这种情况下,您不再需要显式地传递类型和对象参数。Python3实际上为此目的在方法中添加了一个隐式的\uuuuuuuuuuuuuuuuuuuuuuu类
闭包变量。请参见和在Python3.x中,它们修复了相当多的超级调用。。。在python2x中,他们只是没有仔细思考过(我猜…)无论如何,我认为这将以“为什么”问题结束…你可能会发现这很有用:@JoranBeasley-meh,我问过几个为什么类型的问题,之前这些问题都没有结束。@JoranBeasley:对于许多这样的问题,当涉及到Python时,这些原因都有很好的记录,使得这些问题完全可以回答。Python3添加了一个隐式的\uuuu class\uuu
作用域变量,这样您就可以省略参数,super()
将检查调用帧以获取类型和绑定参数(self
或cls
).@jterrace:因为只有没有参数的版本才会在周围范围中查找要绑定到的类型和对象。
class Bar(Foo):
@classmethod
def hello(cls):
print 'hello, bar'
super(Bar).__get__(cls, None).hello()