[Python-checkins] r55061 - peps/trunk/pep-0000.txt peps/trunk/pep-0367.txt
georg.brandl
python-checkins at python.org
Tue May 1 23:11:55 CEST 2007
Author: georg.brandl
Date: Tue May 1 23:11:53 2007
New Revision: 55061
Added:
peps/trunk/pep-0367.txt (contents, props changed)
Modified:
peps/trunk/pep-0000.txt
Log:
Add PEP 367, "New Super" by Calvin Spealman.
Modified: peps/trunk/pep-0000.txt
==============================================================================
--- peps/trunk/pep-0000.txt (original)
+++ peps/trunk/pep-0000.txt Tue May 1 23:11:53 2007
@@ -112,6 +112,7 @@
S 364 Transitioning to the Py3K Standard Library Warsaw
S 365 Adding the pkg_resources module Eby
S 366 Main module explicit relative imports Coghlan
+ S 367 New Super Spealman
S 754 IEEE 754 Floating Point Special Values Warnes
S 3101 Advanced String Formatting Talin
S 3108 Standard Library Reorganization Cannon
@@ -464,6 +465,7 @@
S 364 Transitioning to the Py3K Standard Library Warsaw
S 365 Adding the pkg_resources module Eby
S 366 Main module explicit relative imports Coghlan
+ S 367 New Super Spealman
SR 666 Reject Foolish Indentation Creighton
S 754 IEEE 754 Floating Point Special Values Warnes
P 3000 Python 3000 GvR
@@ -606,6 +608,7 @@
Schneider-Kamp, Peter nowonder at nowonder.de
Seo, Jiwon seojiwon at gmail.com
Smith, Kevin D. Kevin.Smith at theMorgue.org
+ Spealman, Calvin ironfroggy at gmail.com
Stein, Greg gstein at lyra.org
Stutzbach, Daniel daniel.stutzbach at gmail.com
Suzi, Roman rnd at onego.ru
Added: peps/trunk/pep-0367.txt
==============================================================================
--- (empty file)
+++ peps/trunk/pep-0367.txt Tue May 1 23:11:53 2007
@@ -0,0 +1,360 @@
+PEP: 367
+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 (1), 29-Apr-2007 (2)
+
+
+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 our "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 invocation 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 compatibility of the super type API raises some issues.
+Names, the lookup of the ``__call__`` method 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 instantiating
+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 separately may be the best option. A future import or
+even a simple import in 2.x of the new super type from some built-in
+module may offer a way to choose which each module uses, even mixing
+uses by binding to different names. Such a built-in 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 built-in 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.
+
+How does it work in inner functions?
+''''''''''''''''''''''''''''''''''''
+
+If a method defines a function and super is used inside of it, how
+does this work? The frame looking and instance detection breaks here.
+However, if there can be some unambiguous way to use both the new
+super form and still be able to explicitly name the type and instance,
+I think its an acceptable tradeoff to simply be explicit in these
+cases, rather than add weird super-specific lookup rules in these
+cases.
+
+An example of such a problematic bit of code is::
+
+ class B(A):
+ def f(self):
+ def g():
+ return super.f()
+ return g()
+
+Should super actually become a keyword?
+'''''''''''''''''''''''''''''''''''''''
+
+This would solve many of the problems and allow more direct
+implementation of super into the language proper. However, some are
+against the actual keywordization of super. The simplest solution is
+often the correct solution and the simplest solution may well not be
+adding additional keywords to the language when they are not needed.
+Still, it may solve many of the other open issues.
+
+Can we also allow super()?
+''''''''''''''''''''''''''
+
+There is strong sentiment for and against this, but implementation and
+style concerns are obvious. Particularly, that it's "magical" and
+that ``super()`` would differ from ``super.__call__()``, being very
+unpythonic.
+
+
+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'
+
+
+Alternative Proposals
+=====================
+
+No Changes
+----------
+
+Although its always attractive to just keep things how they are,
+people have sought a change in the usage of super calling for some
+time, and for good reason, all mentioned previously.
+
+* Decoupling from the class name (which might not even be bound to the
+ right class anymore!).
+
+* Simpler looking, cleaner super calls would be better.
+
+``super(__this_class__, self)``
+-------------------------------
+
+This is nearly an anti-proposal, as it basically relies on the
+acceptance of the ``__this_class__`` PEP [#pep3130]_, which proposes a
+special name that would always be bound to the class within which it
+is used. If that is accepted, ``__this_class__`` could simply be used
+instead of the class' name explicitly, solving the name binding issues.
+
+``self.__super__.foo(*args)``
+-----------------------------
+
+The ``__super__`` attribute is mentioned in this PEP in several
+places, and could be a candidate for the complete solution, actually
+using it explicitly instead of any super usage directly. However,
+double-underscore names are usually an internal detail, and attempted
+to be kept out of everyday code.
+
+``super(self, *args) or __super__(self, *args)``
+------------------------------------------------
+
+This solution only solves the problem of the type indication, does not
+handle differently named super methods, and is explicit about the name
+of the instance. It is less flexible without being able to enacted on
+other method names, in cases where that is needed. One use case where
+this fails is when a base class has a factory classmethod and a
+subclass has two factory classmethods, both of which need to properly
+make super calls to the one in the base class.
+
+``super.foo(self, *args)``
+--------------------------
+
+This variation actually eliminates the problems with locating the
+proper instance, and if any of the alternatives were pushed into the
+spotlight, I would want it to be this one.
+
+``super`` or ``super()``
+------------------------
+
+This proposal leaves no room for different names, signatures, or
+application to other classes, or instances. A way to allow some
+similar use alongside the normal proposal would be favorable,
+encouraging good design of multiple inheritance trees and compatible
+methods.
+
+
+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)
+
+.. [#pep3130] PEP 3130 (Access to Current Module/Class/Function)
+ http://www.python.org/dev/peps/pep-3130
+
+
+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