[Python-3000] [Python-Dev] 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:
http://www.python.org/download/releases/2.2.3/descrintro/#metaclass_examples
.
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-3000
mailing list