[Python-checkins] r55063 - peps/trunk/pep-0000.txt peps/trunk/pep-3133.txt
guido.van.rossum
python-checkins at python.org
Wed May 2 00:06:35 CEST 2007
Author: guido.van.rossum
Date: Wed May 2 00:06:34 2007
New Revision: 55063
Added:
peps/trunk/pep-3133.txt (contents, props changed)
Modified:
peps/trunk/pep-0000.txt
Log:
Add PEP 3133: New Super (Spealman).
Remove outdated pepparade link.
Modified: peps/trunk/pep-0000.txt
==============================================================================
--- peps/trunk/pep-0000.txt (original)
+++ peps/trunk/pep-0000.txt Wed May 2 00:06:34 2007
@@ -17,10 +17,6 @@
once assigned are never changed. The SVN history[1] of the PEP
texts represent their historical record.
- The BDFL maintains his own Pronouncements page[2] at
- http://www.python.org/doc/essays/pepparade.html which contains his
- musings on the various outstanding PEPs.
-
Index by Category
@@ -132,6 +128,7 @@
S 3130 Access to Current Module/Class/Function Jewett
S 3131 Supporting Non-ASCII Identifiers von Löwis
S 3132 Extended Iterable Unpacking Brandl
+ S 3133 New Super Spealman
S 3141 A Type Hierarchy for Numbers Yasskin
Finished PEPs (done, implemented in Subversion)
@@ -506,6 +503,7 @@
S 3130 Access to Current Module/Class/Function Jewett
S 3131 Supporting Non-ASCII Identifiers von Löwis
S 3132 Extended Iterable Unpacking Brandl
+ S 3133 New Super Spealman
S 3141 A Type Hierarchy for Numbers Yasskin
@@ -635,10 +633,6 @@
[1] View PEP history online
http://svn.python.org/projects/peps/trunk/
- [2] The Benevolent Dictator For Life's Parade of PEPs
- http://www.python.org/doc/essays/pepparade.html
-
-
Local Variables:
mode: indented-text
Added: peps/trunk/pep-3133.txt
==============================================================================
--- (empty file)
+++ peps/trunk/pep-3133.txt Wed May 2 00:06:34 2007
@@ -0,0 +1,254 @@
+PEP: 3133
+Title: New Super
+Version: $Revision$
+Last-Modified: $Date$
+Author: Calvin Spealman <ironfroggy at gmail.com>
+Status: Draft
+Type: Standards Track
+Content-Type: text/x-rst
+Created: 28-Apr-2007
+Python-Version: 2.6
+Post-History: 28-Apr-2007, 29-Apr-2007
+
+
+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)
+
+
+Rationale
+=========
+
+The current usage of super requires an explicit passing of both the class and
+instance it must operate from, requiring a breaking of the DRY (Don't Repeat
+Yourself) rule. This hinders any change in class name, and is often considered
+a wart by many.
+
+
+Specification
+=============
+
+Within the specification section, some special terminology will be used to
+distinguish similar and closely related concepts. "Super type" will refer to
+the actual builtin type named "super". "Next Class/Type in the MRO" will refer
+to the class where attribute lookups will be performed by super, for example,
+in the following, A is the "Next class in the MRO" for the use of super.
+
+ ::
+
+ class A(object):
+ def f(self):
+ return 'A'
+
+ class B(A):
+ def f(self):
+ super(B, self).f() # Here, A would be out "Next class in the
+ # MRO", of course.
+
+A "super object" is simply an instance of the super type, which is associated
+with a class and possibly with an instance of that class. Finally, "new super"
+refers to the new super type, which will replace the original.
+
+Replacing the old usage of super, calls to the next class in the MRO (method
+resolution order) will be made without an explicit super object creation,
+by simply accessing an attribute on the super type directly, which will
+automatically apply the class and instance to perform the proper lookup. The
+following example demonstrates the use of this.
+
+ ::
+
+ 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'
+
+The proposal adds a dynamic attribute lookup to the super type, which will
+automatically determine the proper class and instance parameters. Each super
+attribute lookup identifies these parameters and performs the super lookup on
+the instance, as the current super implementation does with the explicit
+invokation of a super object upon a class and instance.
+
+The enhancements to the super type will define a new __getattr__ classmethod
+of the super type, which must look backwards to the previous frame and locate
+the instance object. This can be naively determined by located the local named
+by the first argument to the function. Using super outside of a function where
+this is a valid lookup for the instance can be considered undocumented in its
+behavior. This special method will actually be invoked on attribute lookups to
+the super type itself, as opposed to super objects, as the current
+implementation works. This may pose open issues, which are detailed below.
+
+"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.
+
+Much of this was discussed in the thread of the python-dev list, "Fixing super
+anyone?" [1]_.
+
+Open Issues
+-----------
+
+__call__ methods
+''''''''''''''''
+
+Backward compatability of the super type API raises some issues. Names, the
+lookup of the __call__ of the super type itself, which means a conflict with
+doing an actual super lookup of the __call__ attribute. Namely, the following
+is ambiguous in the current proposal:
+
+ ::
+
+ super.__call__(arg)
+
+Which means the backward compatible API, which involves instansiating the super
+type, will either not be possible, because it will actually do a super lookup
+on the __call__ attribute, or there will be no way to perform a super lookup on
+the __call__ attribute. Both seem unacceptable, so any suggestions are welcome.
+
+Actually keeping the old super around in 2.x and creating a completely new super
+type seperately may be the best option. A future import or even a simple import
+in 2.x of the new super type from some builtin module may offer a way to choose
+which each module uses, even mixing uses by binding to different names. Such a
+builtin module might be called 'newsuper'. This module is also the reference
+implementation, which I will present below.
+
+super type's new getattr
+''''''''''''''''''''''''
+
+To give the behavior needed, the super type either needs a way to do dynamic
+lookup of attributes on the super type object itself or define a metaclass for
+the builtin type. This author is unsure which, if either, is possible with C-
+defined types.
+
+When should we create __super__ attributes?
+'''''''''''''''''''''''''''''''''''''''''''
+
+They either need to be created on class creation or on __super__ attribute
+lookup. For the second, they could be cached, of course, which seems like it
+may be the best idea, if implicit creation of a super object for every class is
+considered too much overhead.
+
+
+Reference Implementation
+========================
+
+This implementation was a cooperative contribution in the original thread [1]_.
+
+ ::
+
+ #!/usr/bin/env python
+ #
+ # newsuper.py
+
+ import sys
+
+ class SuperMetaclass(type):
+ def __getattr__(cls, attr):
+ calling_frame = sys._getframe().f_back
+ instance_name = calling_frame.f_code.co_varnames[0]
+ instance = calling_frame.f_locals[instance_name]
+ return getattr(instance.__super__, attr)
+
+ class Super(object):
+ __metaclass__ = SuperMetaclass
+ def __init__(self, type, obj=None):
+ if isinstance(obj, Super):
+ obj = obj.__obj__
+ self.__type__ = type
+ self.__obj__ = obj
+ def __get__(self, obj, cls=None):
+ if obj is None:
+ raise Exception('only supports instances')
+ else:
+ return Super(self.__type__, obj)
+ def __getattr__(self, attr):
+ mro = iter(self.__obj__.__class__.__mro__)
+ for cls in mro:
+ if cls is self.__type__:
+ break
+ for cls in mro:
+ if attr in cls.__dict__:
+ x = cls.__dict__[attr]
+ if hasattr(x, '__get__'):
+ x = x.__get__(self, cls)
+ return x
+ raise AttributeError, attr
+
+ class autosuper(type):
+ def __init__(cls, name, bases, clsdict):
+ cls.__super__ = Super(cls)
+
+ if __name__ == '__main__':
+ class A(object):
+ __metaclass__ = autosuper
+ 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, arg=None):
+ var = None
+ return 'D' + Super.f()
+
+ assert D().f() == 'DBCA'
+
+
+History
+=======
+29-Apr-2007 - Changed title from "Super As A Keyword" to "New Super"
+ - Updated much of the language and added a terminology section
+ for clarification in confusing places.
+ - Added reference implementation and history sections.
+
+References
+==========
+
+.. [1] Fixing super anyone?
+ (http://mail.python.org/pipermail/python-3000/2007-April/006667.html)
+
+
+Copyright
+=========
+
+This document has been placed in the public domain.
+
+
+
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ coding: utf-8
+ End:
More information about the Python-checkins
mailing list