[Python-Dev] [Python-3000] Pre-pre PEP for 'super' keyword

Guido van Rossum guido at python.org
Mon Apr 30 05:58:28 CEST 2007

On 4/29/07, Delaney, Timothy (Tim) <tdelaney at avaya.com> wrote:
> I think the current PEP draft is way too complicated - I don't think
> there's any need for descriptors, etc. I think we can make things work
> in the following way:
> 1. When a method is defined, the class is bound to it via an attribute
> (which in my version is called func_class).

In Py3k all the func_XXX attrs are renamed __XXX__, so this would be
__class__; but that's a name reserved for something else, so it would
need to be something else.  E.g. __containing_class__.

Also, this would have to be done when the class is defined; when the
method is being defined the class doesn't exist yet.

> 2. Every non-static method has an implicit cell variable called 'super'.

I think you're using 'cell' in a different sense than it is normally
used in Python's implementation. What you are looking for is called a
local variable (I deduce this from your initialization of the "cell"
with something computed from the first argument). A 'cell' (as I
introduced in my original back-of-the-envelop proposal; apparently you
totally missed this reference) is a special kind of object containing
a reference to another object and used to implement nonlocal variable
references (the Python 2 read-only nonlocals as well as the Python 3
writable nonlocals). The cell is initialized in the surrounding scope
and attached to the function object (as func_closure in 2.x, or
__closure__ in 3.0). When the function is called, a reference to the
cell is stored in the call frame.

If anything in your proposal resembles a cell (in the sense that I and
other Pythonistas mean it), it's the func_class attribute. In fact, in
this sense our proposals are equivalent modulo slight implementation
details; I proposed using a cell because there's an existing mechanism
to get these mapped into a local variable, and because cells are
cheaper than function attributes -- the first function attribute
requires creating a dict, which is one of the larger built-in objects.

> This would preferably not be able to be rebound. I also think it would
> be beneficial if the first parameter to the method couldn't be rebound
> (point 7 in my original email in this thread).

The latter part sounds irrelevant to me.

> 3. When a method is entered, the 'super' cell variable is populated by a
> call equivalent to:
>     super = __builtin__.super(func_class, first_parameter)
> This would result in 'super' being a constant object, within the scope
> of the currently-executing method. 'keyword' was perhaps too strong - I
> was thinking this would only need to be done if 'super' were actually
> used, which would be easier to determine if 'super' actually were a
> keyword. This could still be done by not emitting the above call unless
> the 'super' cell variable were ever actually used.

This sounds about right to me, with the strong preference that super
*should* be made a keyword, and the built-in of the same name renamed
to __super__, as it has a somewhat similar relationship to the super
keyword as the built-in __import__ has to the import keyword.

> I've done bytecode-hacky stuff to do the equivalent of the above (as
> much as I've been able to), but a real implementation would just emit
> the correct bytecode (or java bytecode, or whatever) in the compiled
> code object.

Shouldn't be too hard for someone who's hacked Python/compile.c before.

> The issue of super() vs. super.__call__() ambiguity - I'll need to look
> at that when I get home.

Sounds irrelevant -- if super is equivalent to
__builtin__.__super__(<class>, <firstarg>) then super never gets
called; the only thing ever done to it (in the normal course of
things) is to request an attribute of it.

> I'm a strong -1 against super() automatically passing the parameters
> that were passed to the currently-executing method.

Same here.

There seems to be the remaining controversy that there are three forms
of super calls currently in use:

super(ThisClass, self).method(...)  # in a regular method
super(ThisClass, cls).method(...)  # in a class method
super(ThisClass).method(...)  # ???

The first two are handled by your "use the first argument" approach.

The third exists so that you can create an "unbound" super instance
which is useful for the oft-misunderstood autosuper example in my
"descrintro" essay:

But since the latter is the hack that we're trying to replace with a
proper implementation here, I suspect we can get away with only
supporting the first two forms (and the third form is still supported
using __builtin__.__super__).

IOW I think you're on to something. Keep up the good word.

--Guido van Rossum (home page: http://www.python.org/~guido/)

More information about the Python-Dev mailing list