[Python-Dev] New Super PEP - draft 2 (original) (raw)
Jim Jewett jimjjewett at gmail.com
Sun Apr 29 23:15:33 CEST 2007
- Previous message: [Python-Dev] New Super PEP
- Next message: [Python-Dev] [Python-3000] Pre-pre PEP for 'super' keyword
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
(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
Abstract ========
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:
super.foo(1, 2)
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): ...
into
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?" [1].
I assume you meant the python-3000 list.
-jJ
- Previous message: [Python-Dev] New Super PEP
- Next message: [Python-Dev] [Python-3000] Pre-pre PEP for 'super' keyword
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]