[Python-checkins] r55577 - peps/trunk/pep-0367.txt

neal.norwitz python-checkins at python.org
Fri May 25 09:10:05 CEST 2007


Author: neal.norwitz
Date: Fri May 25 09:10:03 2007
New Revision: 55577

Modified:
   peps/trunk/pep-0367.txt
Log:
Checkpoint from Tim

Modified: peps/trunk/pep-0367.txt
==============================================================================
--- peps/trunk/pep-0367.txt	(original)
+++ peps/trunk/pep-0367.txt	Fri May 25 09:10:03 2007
@@ -2,264 +2,457 @@
 Title: New Super
 Version: $Revision$
 Last-Modified: $Date$
-Author: Calvin Spealman <ironfroggy at gmail.com>
+Author: Calvin Spealman <ironfroggy at gmail.com>,
+        Tim Delaney <timothy.c.delaney 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)
-
+Post-History: 28-Apr-2007, 29-Apr-2007 (1), 29-Apr-2007 (2), 14-May-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::
+This PEP proposes syntactic sugar for use of the ``super`` type to automatically
+construct instances of the super type binding to the class that a method was
+defined in, and the instance (or class object for classmethods) that the method
+is currently acting upon.
+
+The premise of the new super usage suggested is as follows::
 
     super.foo(1, 2)
 
-to replace the old ::
+to replace the old::
 
     super(Foo, self).foo(1, 2)
 
+and the current ``__builtin__.super`` be aliased to ``__builtin__.__super__``
+(with ``__builtin__.super`` to be removed in Python 3.0).
+
+It is further proposed that assignment to ``super`` become a ``SyntaxError``,
+similar to the behaviour of ``None``.
+
 
 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.
+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``. ::
+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". A "super instance" is simply an instance
+of the super type, which is associated with a class and possibly with an
+instance of that class.
+
+Because the new ``super`` semantics are not backwards compatible with Python
+2.5, the new semantics will require a ``__future__`` import::
+
+    from __future__ import new_super
+
+The current ``__builtin__.super`` will be aliased to ``__builtin__.__super__``.
+This will occur regardless of whether the new ``super`` semantics are active.
+It is not possible to simply rename ``__builtin__.super``, as that would affect
+modules that do not use the new ``super`` semantics. In Python 3.0 it is
+proposed that the name ``__builtin__.super`` will be removed.
+
+Replacing the old usage of super, calls to the next class in the MRO (method
+resolution order) can be made without explicitly creating a ``super``
+instance (although doing so will still be supported via ``__super__``). Every
+function will have an implicit local named ``super``. This name behaves
+identically to a normal local, including use by inner functions via a cell,
+with the following exceptions:
+
+1. Assigning to the name ``super`` will raise a ``SyntaxError`` at compile time;
+
+2. Calling a static method or normal function that accesses the name ``super``
+   will raise a ``TypeError`` at runtime.
+
+Every function that uses the name ``super``, or has an inner function that
+uses the name ``super``, will include a preamble that performs the equivalent
+of::
+
+    super = __builtin__.__super__(<class>, <instance>)
+
+where ``<class>`` is the class that the method was defined in, and
+``<instance>`` is the first parameter of the method (normally ``self`` for
+instance methods, and ``cls`` for class methods). For static methods and normal
+functions, ``<class>`` will be ``None``, resulting in a ``TypeError`` being
+raised during the preamble.
 
-    class A(object):
-        def f(self):
-            return 'A'
+Note: The relationship between ``super`` and ``__super__`` is similar to that
+between ``import`` and ``__import__``.
 
-    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. ::
+Much of this was discussed in the thread of the python-dev list, "Fixing super
+anyone?" [1]_.
 
-    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.
+Determining the class object to use
+'''''''''''''''''''''''''''''''''''
+
+The exact mechanism for associating the method with the defining class is not
+specified in this PEP, and should be chosen for maximum performance. For
+CPython, it is suggested that the class instance be held in a C-level variable
+on the function object which is bound to one of ``NULL`` (not part of a class),
+``Py_None`` (static method) or a class object (instance or class method).
 
-When should we create __super__ attributes?
+
+Should ``super`` actually become a keyword?
 '''''''''''''''''''''''''''''''''''''''''''
 
-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.
+With this proposal, ``super`` would become a keyword to the same extent that
+``None`` is a keyword. It is possible that further restricting the ``super``
+name may simplify implementation, however some are against the actual keyword-
+ization 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 other open issues.
+
+
+Closed Issues
+-------------
+
+super used with __call__ attributes
+'''''''''''''''''''''''''''''''''''
+
+It was considered that it might be a problem that instantiating super instances
+the classic way, because calling it would lookup the __call__ attribute and
+thus try to perform an automatic super lookup to the next class in the MRO.
+However, this was found to be false, because calling an object only looks up
+the __call__ method directly on the object's type. The following example shows
+this in action.
+
+::
+
+    class A(object):
+        def __call__(self):
+            return '__call__'
+        def __getattribute__(self, attr):
+            if attr == '__call__':
+                return lambda: '__getattribute__'
+    a = A()
+    assert a() == '__call__'
+    assert a.__call__() == '__getattribute__'
+
+In any case, with the renaming of ``__builtin__.super`` to
+``__builtin__.__super__`` this issue goes away entirely.
 
 
 Reference Implementation
 ========================
 
-This implementation was a cooperative contribution in the original thread [1]_. ::
+It is impossible to implement the above specification entirely in Python. This
+reference implementation has the following differences to the specification:
+
+1. New ``super`` semantics are implemented using bytecode hacking.
+
+2. Assignment to ``super`` is not a ``SyntaxError``. Also see point #4.
+
+3. Classes must either use the metaclass ``autosuper_meta`` or inherit from
+   the base class ``autosuper`` to acquire the new ``super`` semantics.
+
+4. ``super`` is not an implicit local variable. In particular, for inner
+   functions to be able to use the super instance, there must be an assignment
+   of the form ``super = super`` in the method.
+
+The reference implementation assumes that it is being run on Python 2.5+.
+
+::
 
     #!/usr/bin/env python
     #
-    # newsuper.py
-
-    import sys
+    # autosuper.py
 
-    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
+    from array import array
+    import dis
+    import new
+    import types
+    import __builtin__
+    __builtin__.__super__ = __builtin__.super
+    del __builtin__.super
+
+    # We need these for modifying bytecode
+    from opcode import opmap, HAVE_ARGUMENT, EXTENDED_ARG
+
+    LOAD_GLOBAL = opmap['LOAD_GLOBAL']
+    LOAD_NAME = opmap['LOAD_NAME']
+    LOAD_CONST = opmap['LOAD_CONST']
+    LOAD_FAST = opmap['LOAD_FAST']
+    LOAD_ATTR = opmap['LOAD_ATTR']
+    STORE_FAST = opmap['STORE_FAST']
+    LOAD_DEREF = opmap['LOAD_DEREF']
+    STORE_DEREF = opmap['STORE_DEREF']
+    CALL_FUNCTION = opmap['CALL_FUNCTION']
+    STORE_GLOBAL = opmap['STORE_GLOBAL']
+    DUP_TOP = opmap['DUP_TOP']
+    POP_TOP = opmap['POP_TOP']
+    NOP = opmap['NOP']
+    JUMP_FORWARD = opmap['JUMP_FORWARD']
+    ABSOLUTE_TARGET = dis.hasjabs
+
+    def _oparg(code, opcode_pos):
+        return code[opcode_pos+1] + (code[opcode_pos+2] << 8)
+
+    def _bind_autosuper(func, cls):
+        co = func.func_code
+        name = func.func_name
+        newcode = array('B', co.co_code)
+        codelen = len(newcode)
+        newconsts = list(co.co_consts)
+        newvarnames = list(co.co_varnames)
+
+        # Check if the global 'super' keyword is already present
+        try:
+            sn_pos = list(co.co_names).index('super')
+        except ValueError:
+            sn_pos = None
+
+        # Check if the varname 'super' keyword is already present
+        try:
+            sv_pos = newvarnames.index('super')
+        except ValueError:
+            sv_pos = None
+
+        # Check if the callvar 'super' keyword is already present
+        try:
+            sc_pos = list(co.co_cellvars).index('super')
+        except ValueError:
+            sc_pos = None
+
+        # If 'super' isn't used anywhere in the function, we don't have anything to do
+        if sn_pos is None and sv_pos is None and sc_pos is None:
+            return func
+
+        c_pos = None
+        s_pos = None
+        n_pos = None
+
+        # Check if the 'cls_name' and 'super' objects are already in the constants
+        for pos, o in enumerate(newconsts):
+            if o is cls:
+                c_pos = pos
+
+            if o is __super__:
+                s_pos = pos
+
+            if o == name:
+                n_pos = pos
+
+        # Add in any missing objects to constants and varnames
+        if c_pos is None:
+            c_pos = len(newconsts)
+            newconsts.append(cls)
+
+        if n_pos is None:
+            n_pos = len(newconsts)
+            newconsts.append(name)
+
+        if s_pos is None:
+            s_pos = len(newconsts)
+            newconsts.append(__super__)
+
+        if sv_pos is None:
+            sv_pos = len(newvarnames)
+            newvarnames.append('super')
+
+        # This goes at the start of the function. It is:
+        #
+        #   super = __super__(cls, self)
+        #
+        # If 'super' is a cell variable, we store to both the
+        # local and cell variables (i.e. STORE_FAST and STORE_DEREF).
+        #
+        preamble = [
+            LOAD_CONST, s_pos & 0xFF, s_pos >> 8,
+            LOAD_CONST, c_pos & 0xFF, c_pos >> 8,
+            LOAD_FAST, 0, 0,
+            CALL_FUNCTION, 2, 0,
+        ]
+
+        if sc_pos is None:
+            # 'super' is not a cell variable - we can just use the local variable
+            preamble += [
+                STORE_FAST, sv_pos & 0xFF, sv_pos >> 8,
+            ]
+        else:
+            # If 'super' is a cell variable, we need to handle LOAD_DEREF.
+            preamble += [
+                DUP_TOP,
+                STORE_FAST, sv_pos & 0xFF, sv_pos >> 8,
+                STORE_DEREF, sc_pos & 0xFF, sc_pos >> 8,
+            ]
+
+        preamble = array('B', preamble)
+
+        # Bytecode for loading the local 'super' variable.
+        load_super = array('B', [
+            LOAD_FAST, sv_pos & 0xFF, sv_pos >> 8,
+        ])
+
+        preamble_len = len(preamble)
+        need_preamble = False
+        i = 0
+
+        while i < codelen:
+            opcode = newcode[i]
+            need_load = False
+            remove_store = False
+
+            if opcode == EXTENDED_ARG:
+                raise TypeError("Cannot use 'super' in function with EXTENDED_ARG opcode")
+
+            # If the opcode is an absolute target it needs to be adjusted
+            # to take into account the preamble.
+            elif opcode in ABSOLUTE_TARGET:
+                oparg = _oparg(newcode, i) + preamble_len
+                newcode[i+1] = oparg & 0xFF
+                newcode[i+2] = oparg >> 8
+
+            # If LOAD_GLOBAL(super) or LOAD_NAME(super) then we want to change it into
+            # LOAD_FAST(super)
+            elif (opcode == LOAD_GLOBAL or opcode == LOAD_NAME) and _oparg(newcode, i) == sn_pos:
+                need_preamble = need_load = True
+
+            # If LOAD_FAST(super) then we just need to add the preamble
+            elif opcode == LOAD_FAST and _oparg(newcode, i) == sv_pos:
+                need_preamble = need_load = True
+
+            # If LOAD_DEREF(super) then we change it into LOAD_FAST(super) because
+            # it's slightly faster.
+            elif opcode == LOAD_DEREF and _oparg(newcode, i) == sc_pos:
+                need_preamble = need_load = True
+
+            if need_load:
+                newcode[i:i+3] = load_super
+
+            i += 1
+
+            if opcode >= HAVE_ARGUMENT:
+                i += 2
+
+        # No changes needed - get out.
+        if not need_preamble:
+            return func
+
+        # Our preamble will have 3 things on the stack
+        co_stacksize = max(3, co.co_stacksize)
+
+        # Conceptually, our preamble is on the `def` line.
+        co_lnotab = array('B', co.co_lnotab)
+
+        if co_lnotab:
+            co_lnotab[0] += preamble_len
+        
+        co_lnotab = co_lnotab.tostring()
+
+        # Our code consists of the preamble and the modified code.
+        codestr = (preamble + newcode).tostring()
+
+        codeobj = new.code(co.co_argcount, len(newvarnames), co_stacksize,
+                           co.co_flags, codestr, tuple(newconsts), co.co_names,
+                           tuple(newvarnames), co.co_filename, co.co_name,
+                           co.co_firstlineno, co_lnotab, co.co_freevars,
+                           co.co_cellvars)
+
+        func.func_code = codeobj
+        func.func_class = cls
+        return func
 
-    class autosuper(type):
+    class autosuper_meta(type):
         def __init__(cls, name, bases, clsdict):
-            cls.__super__ = Super(cls)
+            UnboundMethodType = types.UnboundMethodType
+
+            for v in vars(cls):
+                o = getattr(cls, v)
+                if isinstance(o, UnboundMethodType):
+                    _bind_autosuper(o.im_func, cls)
+
+    class autosuper(object):
+        __metaclass__ = autosuper_meta
 
     if __name__ == '__main__':
-        class A(object):
-            __metaclass__ = autosuper
+        class A(autosuper):
             def f(self):
                 return 'A'
 
         class B(A):
             def f(self):
-                return 'B' + Super.f()
+                return 'B' + super.f()
 
         class C(A):
             def f(self):
-                return 'C' + Super.f()
+                def inner():
+                    return 'C' + super.f()
+
+                # Needed to put 'super' into a cell
+                super = super
+                return inner()
 
         class D(B, C):
             def f(self, arg=None):
                 var = None
-                return 'D' + Super.f()
+                return 'D' + super.f()
 
         assert D().f() == 'DBCA'
 
+Disassembly of B.f and C.f reveals the different preambles used when ``super``
+is simply a local variable compared to when it is used by an inner function.
+
+::
+
+    >>> dis.dis(B.f)
+
+    214           0 LOAD_CONST               4 (<type 'super'>)
+                  3 LOAD_CONST               2 (<class '__main__.B'>)
+                  6 LOAD_FAST                0 (self)
+                  9 CALL_FUNCTION            2
+                 12 STORE_FAST               1 (super)
+
+    215          15 LOAD_CONST               1 ('B')
+                 18 LOAD_FAST                1 (super)
+                 21 LOAD_ATTR                1 (f)
+                 24 CALL_FUNCTION            0
+                 27 BINARY_ADD          
+                 28 RETURN_VALUE        
+
+::
+
+    >>> dis.dis(C.f)
+
+    218           0 LOAD_CONST               4 (<type 'super'>)
+                  3 LOAD_CONST               2 (<class '__main__.C'>)
+                  6 LOAD_FAST                0 (self)
+                  9 CALL_FUNCTION            2
+                 12 DUP_TOP             
+                 13 STORE_FAST               1 (super)
+                 16 STORE_DEREF              0 (super)
+
+    219          19 LOAD_CLOSURE             0 (super)
+                 22 LOAD_CONST               1 (<code object inner at 00C160A0, file "autosuper.py", line 219>)
+                 25 MAKE_CLOSURE             0
+                 28 STORE_FAST               2 (inner)
+
+    223          31 LOAD_FAST                1 (super)
+                 34 STORE_DEREF              0 (super)
+
+    224          37 LOAD_FAST                2 (inner)
+                 40 CALL_FUNCTION            0
+                 43 RETURN_VALUE        
+
+Note that in the final implementation, the preamble would not be part of the
+bytecode of the method, but would occur immediately following unpacking of
+parameters.
+
 
 Alternative Proposals
 =====================
@@ -267,71 +460,103 @@
 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!).
+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
 
-* Simpler looking, cleaner super calls would be better.
-
-``super(__this_class__, self)``
+Dynamic attribute on super type
 -------------------------------
 
-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.
+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 instance upon a class and instance.
+
+This proposal relies on sys._getframe(), which is not appropriate for anything
+except a prototype implementation.
+
+
+super(__this_class__, self)
+---------------------------
+
+This is nearly an anti-proposal, as it basically relies on the acceptance of
+the __this_class__ PEP, 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 [2]_.
 
-``super.foo(self, *args)``
+self.__super__.foo(\*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.
+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 flexable without being able to enacted on other method
+names, in cases where that is needed. One use case this fails is where a base-
+class has a factory classmethod and a subclass has two factory classmethods,
+both of which needing 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
+inheritence trees and compatible methods.
+
+super(\*p, \*\*kw)
+------------------
+
+There has been the proposal that directly calling ``super(*p, **kw)`` would
+be equivalent to calling the method on the ``super`` object with the same name
+as the method currently being executed i.e. the following two methods would be
+equivalent:
+
+::
+
+    def f(self, *p, **kw):
+        super.f(*p, **kw)
+
+::
+
+    def f(self, *p, **kw):
+        super(*p, **kw)
+
+There is strong sentiment for and against this, but implementation and style
+concerns are obvious. Guido has suggested that this should be excluded from
+this PEP on the principle of KISS (Keep It Simple Stupid).
+
 
 
 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.
 
-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.
-
+06-May-2007 - Updated by Tim Delaney to reflect discussions on the python-3000
+              and python-dev mailing lists.
 
 References
 ==========
@@ -339,8 +564,8 @@
 .. [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
+.. [2] PEP 3130: Access to Module/Class/Function Currently Being Defined (this)
+   (http://mail.python.org/pipermail/python-ideas/2007-April/000542.html)
 
 
 Copyright


More information about the Python-checkins mailing list