(Adding python-3000 to the Cc, since that is where much of the recent discussion occurred)
Calvin's full proposal is archived at: http://mail.python.org/pipermail/python-dev/2007-April/072835.html
The PEP defines the proposal to enhance the super builtin to work implicitly upon the class within which it is used and upon the instance the current function was called on. The premise of the new super usage suggested is as follows:
to replace the old:
super(Foo, self).foo(1, 2)
The alternatives section needs to explain why "super.foo(*args)" is the right level of simplification. Alternatives include
(1) No changes
Con: fragility in name binding
(2) super(__this_class__, self).foo(*args)
Con: The "(__this_class__, self)" is boilerplate.
Note that the __this_class__ PEP should be referenced, if only as a possible explanation for what is happening under the covers.
(3) self.__super__.foo(args) # or super.foo(args)
Con: Shouldn't need a __double_underscore_name__ in normal functions. Con: __super__ (even if renamed super) is not a simple attribute; it is a property representing a partially applied function (that gets further applied by the "self")
(4) super(self, args) # ? or __super__(self, args)
Actually, I sort of like this one, as it allows the upcall signature to exactly match the method definition signature.
Con: super is still not a simple attribute. Con: changing the method name becomes a hassle.
(5) super.foo(self, args) # ? or __super__.foo(self, args)
Con: self isn't really an argument just to super.foo -- it is an argument to super which is used to find/instantiate foo in the first place. (Plus the objections to partially applied function attributes.)
(6) super # ? or super()
Pro: matches java; doesn't require a repeat of *args Con: doesn't match anything else in python, needs to be a keyword (and would still need object support).
In the first example:
class A(object): def f(self): return 'A' class B(A): def f(self): return 'B' + super.f() class C(A): def f(self): return 'C' + super.f() class D(B, C): def f(self): return 'D' + super.f() assert D().f() == 'DBCA'
You should probably include tests that fail with some of the more obvious (but wrong) solutions, such as
class A(object): def f(self): return 'A' class Bempty(A): # Make sure it doesn't call the A or B method twice pass class B(Bempty): def f(self): return 'B' + super.f() class C(A): def f(self): return 'C' + super.f() class D(B, C): def f(self): return 'D' + super.f() assert D().f() == 'DBCA' class E(C, B): # Show that B can point to C as next or vice versa def f(self): return 'E' + super.f() assert E().f() == 'ECBA' class F(D): # show that the instance may not be a direct instance pass assert D().f() == 'DBCA'
The enhancements to the super type will define a new __getattr__ classmethod of the super type,
Did you really mean, it gets the class of builtin.super, but no info on which class is using super? If not, it isn't a classmethod of the super type. It may be a classmethod of the currently-being-defined-type (__this_class__).
which must look backwards to the previous frame and locate the instance object.
frame manipulation is fragile. Even if it didn't cause problems for other implementations, it causes problems for nested functions and callbacks.
def f(self, button, *args): def callback(*args): super(__this_class__, self).f(*args) button.callback=callback
When this gets called, the appropriate self won't be in the frame, except as a lexically scoped variable (which might have a different name).
Also, note that this fails on most of Thomas Wouters' advanced usages. While you say that super shouldn't be called outside a method, you can't really keep the super object itself from getting returned.
"Every class will gain a new special attribute, __super__, which refers to an instance of the associated super object for that class" In this capacity, the new super also acts as its own descriptor, create an instance-specific super upon lookup.
If you didn't say instance-specific, this would be equivalent to a class decorator, translating
class A(object): ...
class A(object): ... A.__super__=super(A)
As is, it gets a bit trickier, since you need to I think the translation is closer to
class A(object):... @property def __super__(self): return __this_class__.__supermaker() A.__supermaker=super(A)
I don't see a good non-magical way to pass both the instance and the class-at-time-of-writing (as opposed to class of calling instance), which is why the other solutions used bytecode hacks or name mangling.
Much of this was discussed in the thread of the python-dev list, "Fixing super anyone?" _.
I assume you meant the python-3000 list.