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