This works as expected:
>>> 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
I can also call the base class explicitly:
>>> class Bar(Foo):
... @classmethod
... def hello(cls):
... print 'hello, bar'
... Foo.hello()
...
>>> b = Bar()
>>> b.hello()
hello, bar
hello, foo
I was wondering why I can't omit the first argument to super
, like this:
>>> 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'
when the result of the super
call without a second argument seems to be a class type inside a super type:
>>> 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'>
I guess I'm just wondering about the design here. Why would I need to pass the class object into the super call to get a reference to the base class type Foo
? For a normal method, it makes sense to pass self
to the function, since it needs to bind the base class type to an actual instance of the class. But a classmethod doesn't need a specific instance of the class.
EDIT:
I get the same error in Python 3.2 as I do above in 2.7 for super(Bar).hello()
. However, I can simply do super().hello()
and that works fine.
super()
returns a descriptor, and needs two items:For the two argument (and implicit zero-argument *) case the second argument is used to bind to, but if you do not pass in a second argument,
super()
cannot invoke the descriptor protocol to bind the returned functions, classmethods, properties or other descriptors.classmethods
are still descriptors and are bound; the bind to a class and not an instance, butsuper()
does not know how the descriptor will use the context to which you bind.super()
should not and cannot know that you are looking up a class method instead of a regular method; class methods only differ from regular methods because their.__get__()
method acts differently.Why are class methods bound? Because when you subclass
Foo
but do not override.hello()
, callingBar.hello()
invokes theFoo.__dict__['hello']
function, binds it toBar
and your first argument tohello(cls)
will be that subclass, notFoo
.Without a second argument,
super()
returns an unbound object that can manually be bound later on. You can do the binding yourself using the.__get__()
method provided by thesuper()
instance:super().__get__()
on an instance without a context effectively returns a newsuper()
instance with the context set. On an instance with a context.__get__()
just returnsself
; it is already bound.* In Python 3, calling
super()
without arguments from inside a bound method will use the calling frame to discover, implicitly, what the type and bound object are, so you no longer have to explicitly pass in the type and object arguments in that case. Python 3 actually adds a implicit__class__
closure variable to methods for this purpose. See PEP 3135 and Why is Python 3.x's super() magic?