Python's super() considered super!

Stefan Behnel stefan_ml at behnel.de
Fri May 27 17:49:37 EDT 2011


Steven D'Aprano, 27.05.2011 18:06:
> On Fri, 27 May 2011 08:31:40 -0700, sturlamolden wrote:
>
>> On 27 Mai, 17:05, Duncan Booth<duncan.bo... at invalid.invalid>  wrote:
>>
>>> Oops. There's a reason why Python 2 requires you to be explicit about
>>> the class; you simply cannot work it out automatically at run time.
>>> Python 3 fixes this by working it out at compile time, but for Python 2
>>> there is no way around it.
>>
>> Then it should be a keyword, not a function.
>
> Why?

I think Sturla is referring to the "compile time" bit. CPython cannot know 
that the builtin super() will be called at runtime, even if it sees a 
"super()" function call.

CPython doesn't evaluate the super call at compile time, it only keeps a 
reference to the surrounding class in the code object of the method. So 
super() without arguments basically inherits the class argument from the 
context the method was found in at compile time. This has two quirks:

1) Copying a method from one class to another keeps the original context. 
So the class argument to super() is basically fixed at compile time, 
regardless of the class the method will be executed on at runtime.

2) The class is only kept as a reference when CPython sees a function call 
that looks like "super" at compile time, which isn't much more than a 
heuristic.

The PEP doesn't mention the first issue, but it is actually explicit about 
the second issue:

http://www.python.org/dev/peps/pep-3135/

"""
While super is not a reserved word, the parser recognizes the use of super 
in a method definition and only passes in the __class__ cell when this is 
found. Thus, calling a global alias of super without arguments will not 
necessarily work.
"""

And the prove:

   >>> _super = super
   >>> class T(object):
   ...   def test(self): print('TEST')
  ...
   >>> class B(T):
   ...   def meth(self): _super().test()
   ...
   >>> B().meth()
   Traceback (most recent call last):
   SystemError: super(): __class__ cell not found

I assume this is done in order to reduce the chance of accidentally keeping 
a class object alive for eternity, only because a method was originally 
defined therein that inherits the class reference in its code object. So 
it's a tradeoff between memory overhead and usability issues.

While I think that the tradeoff is generally ok, I agree with Sturla that a 
keyword would have been the correct solution, whereas this is a clear 
"works only in the common cases" approach.

Stefan




More information about the Python-list mailing list