A normal super
object (what you normally get from calling super(MyType, self)
or super()
or super(MyType, myobj)
) keeps track of both the type and the object it was created with. Whenever you look up an attribute on the super
, it skips over MyType
in the method resolution order, but if it finds a method it binds it to that self
object.
An unbound super
has no self
object. So, super(cls)
skips over cls
in the MRO to find the method foo
, and then binds it to… oops, it has nothing to call it on.
So, what things can you call a classmethod
on? The class itself, or a subclass of it, or an instance of that class or subclass. So, any of those will work as the second argument to super
here, the most obvious one being:
super(cls, cls)
This is somewhat similar to the difference between staticmethods (bound staticmethods
are actually bound to nothing) and classmethods
(bound classmethods
are bound to the class instead of an instance), but it's not quite that simple.
If you want to know why an unbound super
doesn't work, you have to understand what an unbound super
really is. Unfortunately, the only explanation in the docs is:
If the second argument is omitted, the super object returned is unbound.
What does this mean? Well, you can try to work it out from first principles as a parallel to what it means for a method to be unbound (except, of course, that unbound methods aren't a thing in modern Python), or you can read the C source, or the original introduction to 2.2's class-type unification (including a pure-Python super
clone).
A super
object has a __self__
attribute, just like a method object. And super(cls)
is missing its __self__
, just like str.split
is.1
You can't use an unbound super
explicitly the way you can with an unbound method (e.g., str.split('123', '2')
does the same as '123'.split('2')
, but super(cls).foo(cls)
doesn't work the same as super(cls, cls).foo()
). But you can use them implicitly, the same way you do with unbound methods all the time without normally thinking about it.
If you don't know how methods work, the tl'dr is: when you evaluate myobj.mymeth
, Python looks up mymeth
, doesn't find it on myobj
itself, but does find it on the type, so it checks whether it's a non-data descriptor, and, if so, calls its __get__
method to bind it to myobj
.
So, unbound methods2 are non-data descriptors whose __get__
method returns a bound method. Unbound @classmethod
s are similar, but their __get__
ignores the object and returns a bound method bound to the class. And so on.
And unbound super
s are non-data descriptors whose __get__
method returns a bound super
.
Example (credit to wim for coming up with the closest thing to a use for unbound super
that I've seen):
class A:
def f(self): print('A.f')
class B(A):
def f(self): print('B.f')
b = B()
bs = super(B)
B.bs = bs
b.bs.f()
We created an unbound super bs
, stuck it on the type B
, and then b.bs
is a normal bound super, so b.bs.f
is A.f
, just like super().f
would have been inside a B
method.
Why would you want to do that? I'm not sure. I've written all kinds of ridiculously dynamic and reflective code in Python (e.g., for transparent proxies to other interpreters), and I can't remember ever needing an unbound super
. But if you ever need it, it's there.
1. I'm cheating a bit here. First, unbound methods aren't a thing anymore in Python 3—but functions work the same way, so Python uses them where it used to use unbound methods. Second, str.split
, being a C builtin, wasn't properly an unbound method even in 2.x—but it acts like one anyway, at least as far as we're concerned here.
2. Actually plain-old functions.
super(cls)
tosuper(cls, cls)
. With the single-argument form, you end up looking for afoo
method in the parent class ofFoo
(which isobject
). – Armagnacsuper(cls)
here? Unbound supers are rarely useful, and they aren't what you're looking for here. If you're just trying to call the parent class ofcls
'sfoo
classmethod, that'ssuper(cls, cls).foo()
, just like you'd do with an instance for an method. If you're trying to do something different… then what? – Molini