summaryrefslogtreecommitdiff
path: root/pypers
diff options
context:
space:
mode:
authormichele.simionato <devnull@localhost>2008-10-15 05:34:50 +0000
committermichele.simionato <devnull@localhost>2008-10-15 05:34:50 +0000
commit80561be657f8b7e7717112e1b3a6cc5e179d738b (patch)
tree872bcd9b013c364bdac2386b30d098b8f65b6aab /pypers
parent01eef208eb48cdb271c57a6f3218b75112d8d669 (diff)
downloadmicheles-80561be657f8b7e7717112e1b3a6cc5e179d738b.tar.gz
Various stuff
Diffstat (limited to 'pypers')
-rwxr-xr-xpypers/super/ex.py35
-rw-r--r--pypers/super/super2.txt779
2 files changed, 22 insertions, 792 deletions
diff --git a/pypers/super/ex.py b/pypers/super/ex.py
index 6a8489a..089dea9 100755
--- a/pypers/super/ex.py
+++ b/pypers/super/ex.py
@@ -1,19 +1,28 @@
# ex.py
class B(object):
- def __init__(self, *args):
- print "B.__init__"
- super(B, self).__init__(*args)
-
-class M(B, type):
- def __init__(self, n, b, d):
- print "M.__init__"
- super(M, self).__init__(n, b, d)
-
+ def __repr__(self):
+ return '<instance of %s>' % self.__class__.__name__
+ def meth(self):
+ print "B.meth(%s)" % self
+ meth = classmethod(meth)
+
class C(B):
- __metaclass__ = M
- def __init__(self):
- print "C.__init__"
- super(C, self).__init__()
+ def meth(self):
+ print "C.meth(%s)" % self
+ self.__super.meth()
+ meth = classmethod(meth)
+
+C._C__super = super(C)
+
+class D(C):
+ pass
+
+D._D__super = super(D)
+
+
+d=D()
+
+d.meth()
diff --git a/pypers/super/super2.txt b/pypers/super/super2.txt
deleted file mode 100644
index 4458a01..0000000
--- a/pypers/super/super2.txt
+++ /dev/null
@@ -1,779 +0,0 @@
-Ten things to know about ``super``
-====================================
-
-:Author: Michele Simionato
-:Email: michele.simionato@gmail.com
-:Initial Draft: June 2004
-:Last Revision: May 2008
-:Version: 0.6
-
-``super`` is Python a built-in, first introduced in Python 2.2 and
-slightly improved and fixed in later versions, which is often
-misunderstood by the average Python programmer. One of the reasons for
-that, is the poor documentation of ``super``: at the time of this
-writing (May 2008) the documentation is incomplete and in some parts
-misleading and even wrong. For instance, the standard documentation
-(even for the new 2.6 version
-http://docs.python.org/dev/library/functions.html#super) still says::
-
- super(type[, object-or-type])
- Return the superclass of type. If the second argument is omitted the
- super object returned is unbound. If the second argument is an object,
- isinstance(obj, type) must be true. If the second argument is a type,
- issubclass(type2, type) must be true. super() only works for new-style
- classes.
-
-The first sentence is just plain wrong: ``super`` does not return the
-superclass. There is no such a thing as "the" superclass in a Multiple
-Inheritance (MI) world. Also, the sentence about *unbound* is misleading,
-since it may easily lead the programmer to think about bound and unbound
-methods, whereas it has nothing to do with that concept. Finally, there are
-subtle pitfalls and dark corners of ``super`` which are not at all mentioned.
-IMNSHO ``super`` is one of the most trickiest and surprising Python
-constructs, and we absolutely needs a document to shed light on its secrets.
-The present paper is a first step in this direction: it aims to tell you
-the *truth* about ``super``. At least the amount of truth
-I have discovered with my experimentations, which is certainly
-not the whole truth ;)
-
-A fair warning is in order here: this document is aimed to expert
-Pythonistas. It assumes you are familiar with new-style classes [#]_
-and the Method Resolution Order (MRO_)
-concept; moreover a good understanding of descriptors_ would be extremely
-useful in order to grasp this document. Some parts also require good
-familiarity with metaclasses_. All in all, this paper is not for the faint
-of heart ;)
-
-.. _MRO: http://www.python.org/download/releases/2.3/mro/
-.. _descriptors: http://users.rcn.com/python/download/Descriptor.htm
-.. _metaclasses: http://www.ibm.com/developerworks/library/l-pymeta.html
-
-First thing: there is no superclass in a MI world
-----------------------------------------------------------
-
-Readers familiar will single inheritance languages, such as
-Java or Smalltalk, will have a clear concept of superclass
-in mind. This concept, however, has *no useful meaning* in Python or in
-other multiple inheritance languages. I became convinced of this fact
-after a discussion with Bjorn Pettersen and Alex Martelli
-on comp.lang.python in May 2003 [#]_
-(at that time I was mistakenly thinking that one could define a
-superclass concept in Python). Consider this example from that
-discussion:
-
- ::
-
- +-----+
- | T |
- |a = 0|
- +-----+
- / \
- / \
- +-------+ +-------+
- | A | | B |
- | | | a = 2 |
- +-------+ +-------+
- \ /
- \ /
- +-----+
- | C |
- +-----+
- :
- : instantiation
- c
-
->>> class T(object):
-... a = 0
-
->>> class A(T):
-... pass
-
->>> class B(T):
-... a = 2
-
->>> class C(A,B):
-... pass
-
->>> c = C()
-
-Which is the superclass of ``C``? There are two direct superclasses (i.e. bases)
-of ``C``: ``A`` and ``B``. ``A`` comes before ``B``, so one would naturally
-think that the superclass of ``C`` is ``A``. Iif ``super(C,c)`` was returning
-the superclass of ``C``,
-then it should return ``A``. ``A`` inherits its attribute ``a`` from ``T``,
-where ``a`` has the value 0, so ``super(C,c).a`` should return 0. This
-is NOT what happens. Instead, ``super(C,c).a`` walks trought the
-method resolution order of the class of ``c`` (i.e. ``C``)
-and retrieves the attribute from the first class above ``C`` which
-defines it. In this example the MRO of ``C`` is ``[C, A, B, T, object]``, so
-``B`` is the first class above ``C`` which defines ``a`` and ``super(C,c).a``
-correctly returns the value 2, not 0:
-
->>> super(C,c).a
-2
-
-You may call ``A`` the superclass of ``C``, but this is not an useful
-concept since the methods are resolved by looking at the classes
-in the MRO of ``C``, and not by looking at the classes in the MRO of ``A``
-(which in this case is ``[A,T, object]`` and does not contain ``B``).
-The whole MRO is needed, not just the first superclass.
-
-So, using the word *superclass* in the standard doc is completely
-misleading and should be avoided altogether.
-
-Second thing: ``super`` returns proxy objects
-----------------------------------------------------
-
-Having established that ``super`` cannot return and does not return the
-mythical superclass, we may ask ourselves what the hell is returning
-``super`` ;) The truth is that ``super`` returns proxy objects.
-
-Informally speaking, a proxy object is an object with
-the ability to dispatch to methods of other classes via delegation.
-Technically, ``super`` is a class overriding the ``__getattribute__``
-method. Instances of ``super`` are proxy objects providing
-access to the methods in the MRO. The dispatch is done in such a way
-that
-
-``super(cls, instance-or-subclass).meth(*args, **kw)``
-
-corresponds to
-
-``right-method-in-the-MRO-applied-to(instance-or-subclass, *args, **kw)``
-
-There is a caveat at this point: the second argument can be
-an instance of the first argument, or a subclass of it, but
-in *both cases* a bound method is returned (one could naively
-think that when a subclass is passed one gets an unbound method).
-
-For instance, in this example
-
-.. code-block:: python
-
- >>> class B(object):
- ... def __repr__(self):
- ... return "<instance of %s>" % self.__class__.__name__
-
- >>> class C(B):
- ... pass
-
- >>> class D(C):
- ... pass
-
- >>> d = D()
-
-both
-
-.. code-block:: python
-
- >>> print super(C,d).__repr__
- <bound method D.__repr__ of <instance of D>>
-
-and
-
-
-.. code-block:: python
-
- >>> print super(C,D).__repr__
- <bound method D.__repr__ of <class 'D'>>
-
-returns bound methods. This means that when you call the ``__repr__`` methods,
-you will get
-
-
-.. code-block:: python
-
- >>> print super(C,d).__repr__()
- <instance of D>
-
-(here ``d``, a ``D`` instance, is being passed to ``__repr__``) and
-
-.. code-block:: python
-
- >>> print super(C, D).__repr__()
- <instance of type>
-
-(here ``D``, an instance of the (meta)class ``type``, is being passed
-to ``__repr__``).
-
-Reading the docs, one could think that in order to get unbound methods,
-one would need to switch to the alternative syntax of ``super``, the single
-argument syntax. This is actually untrue. To understand how unbound
-methods can be retrieved we need to talk about descriptors.
-
-Third thing: ``super`` returns descriptor objects
-----------------------------------------------------
-
-Descriptors (more properly I should speak of the descriptor protocol) were
-introduced in Python 2.2 by Guido van Rossum. Their primary motivation
-is technical, since they were needed to implement the new-style object
-system. Descriptors were also used to introduce new standard concepts in
-Python, such as classmethods, staticmethods and properties. Moreover,
-according to the traditional transparency policy of Python, descriptors
-were exposed to the application programmer, giving him/her the freedom
-to write custom descriptors. Any serious Python programmer should have
-a look at descriptors: luckily they are now very well documented (which was
-not the case when I first studied them :-/) thanks to the beautiful essay
-of Raimond Hettinger [#]_. You should read it before continuing this article,
-since it explains all the details. However, for the sake of our discussion
-of ``super``, it is enough to say that a *descriptor class* is just a
-regular new-style class which implements a ``.__get__`` method with
-signature ``__get__(self, obj, objtyp = None)``. A *descriptor object*
-is just an instance of a descriptor class.
-
-Descriptor objects are intended to be used as attributes (hence their
-complete name attribute descriptors). Suppose that ``descr`` is a
-given descriptor object used as attribute of a given class C.
-Then the syntax ``C.descr`` is actually interpreted by Python as a
-call to ``descr.__get__(None, C)``, whereas the same syntax for an
-instance of C corresponds to a call to ``descr.__get__(c, type(c))``.
-
-The unbound method ``__repr__`` can be retrieved as
-
-.. code-block:: python
-
- >>> super(C,d).__repr__.__get__(None,D) # or with D instead of d
- <unbound method D.__repr__>
-
-and we may check that it works correctly:
-
-.. code-block:: python
-
- >>> print _(d)
- <instance of D>
-
-This is cumbersome and tricky, but it is the only way to get
-the unbound method. Using the unbound form of ``super`` does
-*not* return ``D.__repr__``: instead it returns ``super.__repr__``
-bound to the (unbound) super object ``super(C)``:
-
-.. code-block:: python
-
- >>> print super(C).__repr__() # same as repr(super(C))
- <super: <class 'C'>, NULL>
-
-Very tricky. Notice that ``super`` also redefines ``__new__``,
-``__init``, ``__get__``, ``__getattribute``, as well as inheriting
-other special attributes from ``object``. So using the single-argument
-syntax you will dispatch to
-these methods in ``super`` and not to the right methods defined in
-the hierarchy at hand. On the other hand, the two-argument syntax
-does not have this problem. For instance
-
-.. code-block:: python
-
- >>> print super(C,C).__repr__()
- <instance of type>
-
-does the right thing.
-
-This other example should shed further light. Suppose ``B``
-has a method called ``meth`` like this:
-
-.. code-block:: python
-
- >>> B.meth = lambda self :'You called B.meth with first argument %s' % self
-
-Then ``B.meth`` is an unbound method and, mislead by the documentation,
-one could expect to be able to access it with the syntax ``super(C).meth``.
-This is not the case. You get an error instead:
-
-.. code-block:: python
-
- >>> super(C).meth
- Traceback (most recent call last):
- ...
- AttributeError: 'super' object has no attribute 'meth'
-
-Unbound super objects cannot be accessed directly,
-they must be converted to bound objects in order to make them
-to dispatch properly. Unbound super objects can be converted to
-bound super objects via the descriptor protocol. For instance,
-in this example I can convert ``super(C)`` in a super object
-bound to ``d`` in this way:
-
-.. code-block:: python
-
- >>> boundsuper = super(C).__get__(d, D) # this is the same as super(C,d)
-
-Now I can access the bound method 'd.meth':
-
-.. code-block:: python
-
- >>> print boundsuper.meth
- <bound method D.<lambda> of <instance of D>>
-
-As a consequence, ``__get__`` cannot be turned into a cooperative method
-just by using ``super``: you would get the wrong ``get``.
-
-Fourth thing: the *unbound* syntax is a mess
-------------------------------------------------------------------
-
-Having established that the *unbound* syntax does not return unbound methods
-one might ask what its purpose is.
-The answer is that ``super(C)`` is intended to be used as an attribute in
-other classes. Then the descriptor magic will automatically convert the
-unbound syntax in the bound syntax. For instance:
-
-.. code-block:: python
-
- >>> class B(object):
- ... a = 1
- >>> class C(B):
- ... pass
- >>> class D(C):
- ... sup = super(C)
- >>> d = D()
- >>> d.sup.a
- 1
-
-This works since ``d.sup.a`` calls ``super(C).__get__(d,D).a`` which is
-converted to ``super(C, d).a`` and retrieves ``B.a``.
-
-There is a single use case for the single argument
-syntax of ``super`` that I am aware of, but I think it gives more troubles
-than advantages. The use case is the implementation of *autosuper* made
-by Guido on his essay about `new-style classes`_.
-
-.. _new-style classes: http://www.python.org/download/releases/2.2.3/descrintro/#cooperation
-
-The idea there is to use the unbound super objects as private
-attributes. For instance, in our example, we could define the
-private attribute ``__sup`` in the class ``C`` as the unbound
-super object ``super(C)``:
-
-.. code-block:: python
-
- >>> C._C__sup = super(C)
-
-With this definition inside the methods the syntax
-``self.__sup.meth(arg)`` can be used
-as an alternative to ``super(C, self).meth(arg)``, and the advantage is
-that you avoid to repeat the name of the class in the calling
-syntax, since that name is hidden in the mangling mechanism of
-private names. The creation of the ``__sup`` attributes can be hidden
-in a metaclass and made automatic. So, all this seems to work: but
-actually this *not* the case.
-
-Things may wrong in various case, for instance for classmethods,
-as in this example:
-
-.. code-block:: python
-
- #<ex.py>
-
- class B(object):
- def __repr__(self):
- return '<instance of %s>' % self.__class__.__name__
- def meth(self):
- print "B.meth(%s)" % self
- meth = classmethod(meth)
-
- class C(B):
- def meth(self):
- print "C.meth(%s)" % self
- self.__super.meth()
- meth = classmethod(meth)
-
- C._C__super = super(C)
-
- class D(C):
- pass
-
- D._D__super = super(D)
-
-
- d=D()
-
- d.meth()
-
- #</ex.py>
-
-The last line raises an ``AttributeError: 'super' object has no attribute
-'meth'.``
-
-So, using a ``__super`` unbound super object is not a robust solution
-(notice that everything would work by substituting ``self.__super.meth()``
-with ``super(C,self).meth()``.
-In Python 3.0 all this has been resolved in a much better way.
-
-.. There are other ways to avoid repeating the class name, see for instance my cookbook recipe [#]_.
-
-If it was me, I would just remove the single argument syntax of ``super``,
-making it illegal. But this would probably break someone code, so
-I don't think it will ever happen in Python 2.X. Another solution would be just to
-deprecate it. There is no need for this syntax, one can always circumvent
-it.
-
-Fifth thing: ``super`` does not work with meta-attributes
-----------------------------------------------------------------------
-
-If you start using ``super`` intensively, soon or latter you will find
-a number of subtilities. One of these is the fact that ``super`` does not
-work well with the ``__name__`` special attribute. Consider this example:
-
-.. code-block:: python
-
- >>> class B(object):
- ... "This is class B"
- ...
- >>> class C(B):
- ... pass
- ...
-
-Here the special (class) attribute ``__doc__`` is retrieved as you would expect:
-
-.. code-block:: python
-
- >>> super(C,C).__doc__ == super(C,C()).__doc__ == B.__doc__
- True
-
-On the other hand, the special attribute ``__name__`` is not
-retrieved correctly:
-
-.. code-block:: python
-
- >>> super(C,C).__name__ # one would expect it to be 'B'
- Traceback (most recent call last):
- File "<stdin>", line 1, in ?
- AttributeError: 'super' object has no attribute '__name__'
-
-The problem is that ``__name__`` is not just a plain class
-attribute: it is actually a "getset descriptor" defined on
-the metaclass "type" (try to run ``help(type.__dict__['__name__'])``
-and you will see for yourself). More in general, ``super`` has
-problems with meta-attributes, i.e. class attributes of metaclasses.
-
-Meta-attributes differs from regular attributes since they are not
-transmitted to the instances of the instances.You can find the
-rationale for this behaviour elsewhere [#]_: here I am only interested
-to the issues with ``super``. Consider this example:
-
-.. code-block:: python
-
- #<example1.py>
-
- class M(type):
- "A metaclass with a class attribute 'a'."
- a = 1
-
- class B:
- "An instance of M with a meta-attribute 'a'."
- __metaclass__ = M
-
- class C(B):
- "An instance of M with the same meta-attribute 'a'"
-
- if __name__ == "__main__":
- print B.a, C.a # => 1 1
- print super(C,C).a #=> attribute error
-
- #</example1.py>
-
-If you run this, you will get an attribute error. This is a case
-where ``super`` is doing the *right* thing, since 'a' is *not* inherited
-from B, but it comes directly from the metaclass (again, look at my second
-article with David Mertz to understand why it is so), so 'a'
-is *not* in the MRO of C. A similar thing happens for the ``__name__``
-attribute (the fact that it is a descriptor and not a plain
-attribute does not matter), so ``super`` is working correctly, but
-still it may seems surprising at first.
-
-Sixth thing: special attribute access for special attributes is special ;)
-----------------------------------------------------------------------------
-
-There is also another subtle pitfall which is not directly related
-to ``super`` but which is often encountered working with ``super``.
-This came up at least three or four times in the newsgroup, and there
-are various independent bug reports on sourceforge about it, so possibly
-you may face it too. Bjorn Pettersen was the first one who pointed out the
-problem to me (see also bug report SF 729913): the issue is that
-
-``super(MyCls, self).__getitem__(5)``
-
-works, but not
-
-``super(MyCls, self)[5]``.
-
-The problem is general to all special methods, not only to ``__getitem__``,
-and the explanation for that has to do with the implementation of
-attribute lookup for special methods. Clear explanations of what is
-going on are provided by Michael Hudson as a comment to the bug report:
-SF789262 and by Raymond Hettinger as a comment to the bug report SF805304.
-Shortly put, this is not a problem of ``super`` per se, the problem is
-that the special call ``x[5]`` (using ``__getitem__`` as example) is
-converted to ``type(x).__getitem__(x,5)``
-*only if* ``__getitem__`` is explicitely defined in ``type(x)``. If
-``type(x)`` does not define ``__getitem__`` directly, but only
-indirectly via delegation (i.e. overriding ``__getattribute__``),
-then the second form works but not the first one.
-
-This restriction will likely stay in Python because it would involve
-a really big change and a loss of performances, so it has to be
-considered just a documentation bug, since nowhere in
-the docs it is mentioned that special calling syntaxes (such as
-the ``[]`` call, the ``iter`` call, the ``repr`` call, etc. etc.)
-are special and bypass ``__getattribute__``. Guido advice is:
-just use the more explicit form and everything will work.
-
-Finally, there may be other bugs and pitfalls I am not aware of. Certainly
-there are many other issues and bugs in previous versions of Python that
-I have not mentioned here, since they have been fixed, but that you may
-encounter if you use Python 2.2 (and maybe even in 2.3).
-
-Seventh thing: mixing super and non-super using methods is tricky
---------------------------------------------------------------------
-
-Some years ago James Knight wrote an eassay titled
-`Super considered harmful`_ [#]_ where he points out a few shortcomings
-of ``super`` and makes an important recommendation:
-*use super consistently, and document that you use it, as it is part of the
-external interface for your class, like it or not*.
-The issue is that a developer inheriting from a hierarchy written by somebody
-else, has to know if the hierarchy author has used ``super`` internally
-or not. For instance, consider this case, where the library author has
-used ``super`` internally:
-
-.. code-block:: python
-
- class A(object):
- def __init__(self):
- print "A",
- super(A, self).__init__()
-
- class B(object):
- def __init__(self):
- print "B",
- super(B, self).__init__()
-
-If the application programmers knows that the library uses ``super`` internally,
-he will use ``super`` and everything will work just fine; but it he does not
-know if the library uses ``super`` he may be tempted to call ``A.__init__``
-and ``B.__init__`` directly, but this will end up in having ``B.__init__``
-called twice!
-
-.. code-block:: python
-
- class C(A,B):
- def __init__(self):
- print "C",
- A.__init__(self)
- B.__init__(self)
-
- # c = C() will print
-
-On the other hand, if the library does not uses ``super`` internally,
-
-.. code-block:: python
-
- class A(object):
- def __init__(self):
- print "A",
-
- class B(object):
- def __init__(self):
- print "B",
-
-the application programmer cannot use ``super`` either, otherwise
-``B.__init__`` will not be called:
-
-.. code-block:: python
-
- class C(A,B):
- def __init__(self):
- print "C",
- super(C, self).__init__()
-
- # c = C() will print
-
-So, if use a library featuring multiple inheritance, you must know if the
-hierarchy was intended to be cooperative (using ``super``) or not.
-
-Eighth thing: argument passing in cooperative methods can fool you
-----------------------------------------------------------------------
-
-James Knight devolves a paragraph to the discussion of argument passing
-in cooperative methods. Basically, if you want to be safe, all your cooperative
-methods should have a compatible signature. There are various ways to
-get a compatible signature, for instance you could accept everything (i.e.
-your cooperative methods could have signature ``*args, **kw``) which is
-a bit too much for me, or all of your methods could have exactly the same
-arguments. The issue comes when you have default arguments, since your
-MRO can change if you change your hierarchy, and argument passing may
-break down. Here is one example
-
-.. code-block:: python
-
- class A(object):
- def __init__(self):
- print 'A'
-
- class B(object):
- def __init__(self, a=None):
- print 'B with a=%s' % a
- super(B, self).__init__(a)
-
- class C(object):
- def __init__(self, a):
- print 'C with a=%s' % a
- super(C, self).__init__()
-
- class D(B, C):
- def __init__(self):
- print 'D'
- super(D, self).__init__()
-
- d = D()
-
-This works, but it is fragile (you see what will happen if you change
-``D(B,C)`` with ``D(C,B)``?) and in general it is always difficult
-to figure out which arguments will be passed to each method and in
-which order (the order changing if you change the hierarchy) so it is
-best just to use the same arguments everywhere (or not to use
-cooperative methods altogether, if you have no need for cooperation).
-There is no shortage of examples of trickiness in multiple inheritance
-hierarchy; for instance I remember a post from comp.lang.python [#]_
-. Also, beware of situations in which you have
-some old style classes mixing with new style classes: the result may
-depend on the order of the base classes (see examples 2-2b and 2-3b
-in `Super considered harmful`_.
-
-.. _Super considered harmful: http://fuhm.net/super-harmful/
-
-Ninth thing: ``super`` had bugs in earlier versions of Python
------------------------------------------------------------------
-
-There are various ``super`` pitfalls currently undocumented of which
-the experienced Python programmer should be aware of.
-
-The unbound form of ``super`` does not play well with pydoc.
-The problems is still there in Python 2.3.4 (see bug report SF729103)
-
-.. code-block:: python
-
- >>> class B(object): pass
- ...
- >>> class C(B):
- ... s=super(B)
- ...
- >>> help(C)
- Traceback (most recent call last):
- ...
- ... lots of stuff here
- ...
- File "/usr/lib/python2.3/pydoc.py", line 1198, in docother
- chop = maxlen - len(line)
- TypeError: unsupported operand type(s) for -: 'type' and 'int'
-
-I have not yet clear what the cause is, but it is certainly quite
-tricky. An incompatibility between ``super`` was reported by Christian Tanzer
-(SF902628); if you run the following, you will get a TypeError:
-
-.. code-block:: python
-
- #<ex.py>
-
- class C(object):
- pass
-
- C.s = super(C)
-
- if __name__ == "__main__":
- import doctest, __main__
- doctest.testmod(__main__)
-
- #<ex.py>
-
-BTW, I don't think this is related to ``super`` only since I have
-found similar problems when playing with descriptors and doctest
-some time ago (but I cannot reproduce the bug right now).
-
-Tenth and last thing: when it comes to ``super`` don't trust even Guido himself!
-----------------------------------------------------------------------------------
-
-In order to explain how ``super`` works, Guido describes a
-"fully functional implementation of the super() built-in class in
-pure Python" in "Unifying types and classes in Python 2.2".
-Unfortunately, that implementation is more harmful than helpful, since
-the current ``super`` DOES NOT work in the same way :-(
-Take for instance this example:
-
-.. code-block:: python
-
- >>> class C(object):
- ... f='C.f'
- >>> class D(C):
- ... f='D.f'
-
-Here the ``super`` works fine,
-
-.. code-block:: python
-
- >>> print super(D,D()).f
- C.f
-
-but the class ``Super`` described by Guido will raise an attribute
-error when invoked as ``Super(D,D()).f``. Therefore ``Super`` is NOT
-equivalent to the currently implemented ``super`` built-in.
-
-Conclusion: is there life beyond super?
--------------------------------------------------------
-
-In this paper I have argued that ``super`` is tricky,
-however the existence of dark corners is not a compelling argument against
-a language construct: after all, they are rare and there is an easy solution to
-their obscurity, i.e. documenting them.
-Also, even from experience I have come to believe that cooperative
-methods are a wart (it is too difficult to reason about them, they are
-fragile, and overall I see them as an unneeded complication in 99.9%
-of the cases) they have their uses in a multiple inheritance world, as
-Guido argues successfully in his essay (the canonical example being a
-diamond diagram with ``.save`` methods which must be called
-cooperatively).
-The problem therefore is not with ``super`` or with cooperative
-methods, the problem is with multiple inheritance itself (*if the
-implementation is hard to explain, it's a bad idea*).
-
-I personally liked super, cooperative methods and multiple inheritance
-for a couple of years, then I started working with Zope and my mind
-changed completely. The problem is multiple inheritance itself: after
-all Zope 2 did not use super at all but is a mess anyway. Inheritance
-makes your code heavily coupled and difficult to follow (*spaghetti
-inheritance*). I have not found a real life problem yet that I could
-not solve with single inheritance + composition/delegation in a better
-and more maintainable way than using multiple inheritance.
-Nowadays I use multiple inheritance for quick and dirty hacks,
-but never for designing new hierarchies from scratch.
-There are alternative to multiple inheritance: for instance Ruby uses
-mixins (they are a restricted multiple inheritance without cooperative
-methods and with a well defined superclass, but they do not solve
-the issue of name conflicts and the issue with the ordering of
-the mixin classes); recently some people proposed the concepts
-of traits (restricted mixin where name conflicts must be solved explicitely
-and the ordering of the mixins does not matter) which is interesting.
-In CLOS multiple inheritance works better since (multi-)methods
-are defined outside classes and ``call-next-method`` is well integrated
-in the language;
-it is simpler to track down the ancestors
-of a single method than to wonder about the full class hierarchy.
-The language SML (which nobody except academics use, but would deserve
-better recognition) goes boldly in the direction of favoring composition over
-inheritance and uses functors to this aim. This is an approach I like very
-much on the paper, but I lack real experience in a large code base to judge
-merits and demerits of this approach.
-
-Notes
------------------
-
-.. [#] http://www.python.org/download/releases/2.2.3/descrintro/
-.. [#] I wrote an essay on Python 2.3 Method Resolution Order which
- you may find here: http://www.python.org/download/releases/2.3/mro/
-.. [#] Raymond Hetting wrote a beautiful essay on descriptors: http://users.rcn.com/python/download/Descriptor.htm
-.. [#] David Mertz and me wrote a trilogy of articles on metaclasses;
- the second one is the relevant one for the issues discussed here:
- http://www-128.ibm.com/developerworks/linux/library/l-pymeta2/
-.. [#] a thread proving that there is no useful concept of superclass
- http://tinyurl.com/5ms8lk
-.. [#] Python's Super is nifty, but you can't use it, http://fuhm.net/super-harmful
-.. [#] A thread about subtle cooperative hierarchies http://tinyurl.com/3jqhx7
-.. [#] Traits: http://www.iam.unibe.ch/~scg/Research/Traits/