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

Calvin Spealman ironfroggy at gmail.com
Mon Apr 30 14:29:22 CEST 2007


On 4/30/07, Delaney, Timothy (Tim) <tdelaney at avaya.com> wrote:
> Guido van Rossum wrote:
>
> >> 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__.
>
> Yep - I've just used a placeholder name.
>
> > Also, this would have to be done when the class is defined; when the
> > method is being defined the class doesn't exist yet.
>
> Good point. Change that to "at the first opportunity" ;)
>
> >> 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).
>
> Actually, I think I'm using the terminology correctly - I'm talking
> about an entry in co_cellvars. Given the following class:
>
>     class A(object):
>         def f(self):
>             super = super_factory()
>
>             def inner():
>                 return 'A' + super.f()
>
>             print inner()
>
> the use of 'super' in both A.f and A.f.inner will produce an entry in
> A.f.func_code.co_cellvars and A.f.inner.func_code.co_freevars. What I'm
> proposing is that the `super = super_factory()` line be implicit in this
> case, resulting in the following code behaving identically:
>
>     class A(object):
>         def f(self):
>             def inner():
>                 return 'A' + super.f()
>
>             print inner()

I believe the direction my PEP took with all this is a good bit
primitive compared to this approach, although I still find value in it
because at least a prototype came out of it that can be used to test
the waters, regardless of if a more direct-in-the-language approach
would be superior.

However, I seem to think that if the __this_class__ PEP goes through,
your version can be simplified as well. No tricky stuffy things in
cells would be needed, but we can just expand the super 'keyword' to
__super__(__this_class__, self), which has been suggested at least
once. It seems this would be much simpler to implement, and it also
brings up a second point.

Also, I like that the super object is created at the beginning of the
function, which my proposal couldn't even do. It is more efficient if
you have multiple super calls, and gets around a problem I completely
missed: what happens if the instance name were rebound before the
implicit lookup of the instance object at the time of the super call?

> >> 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.
>
> Sorry - this is related to my proposal that the following two bits of
> code behave the same:
>
>     class A(object):
>         def f(self, *p, **kw):
>             super.f(*p, **kw)
>
>     class A(object):
>         def f(self, *p, **kw):
>             super(*p, **kw)
>
> But as has been pointed out, this creates an ambiguity with:
>
>     class A(object):
>         def f(self, *p, **kw):
>             super.__call__(*p, **kw)
>
> so I want to see if I can resolve it.

Turns out, it doesn't. A lot of people expect it, but it turns out to
be simple. super(*p, **kw) is not equivalent to super.__call__(*p,
**kw) but to type(super).__call__.__get__(super, type(super))(*p,
**kw), due to operator methods being looked up on the type directly
and bound by the descriptor, without any lookup on the super object
itself. Thus, no attribute is ever done on the super object itself,
type(super).__getattribute__ is never invoked, and there is no problem
at all.

This also means we can still invoke super the old, explicit way.

I've already got my copy of the PEP updated to reflect this.

> > super(ThisClass).method(...)  # ???
> >
> > 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_exam
> ples
> > .
> >
> > 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__).
>
> Yep - that's my thought as well. I think it would be very rare to need
> super(ThisClass), although it makes some sense that that would be what
> super means in a static method ...

Does super mean anything in a static method today?

-- 
Read my blog! I depend on your acceptance of my opinion! I am interesting!
http://ironfroggy-code.blogspot.com/


More information about the Python-Dev mailing list