summaryrefslogtreecommitdiff
path: root/pypers/super/super.html
diff options
context:
space:
mode:
authormichele.simionato <devnull@localhost>2007-12-02 11:13:11 +0000
committermichele.simionato <devnull@localhost>2007-12-02 11:13:11 +0000
commit20ce686b0193d67ea56823a30551140f88b3aee1 (patch)
tree76015e7e4dc0b000bd857a2bdba6fb7976ac29a7 /pypers/super/super.html
parentf08f40335ad7f0ac961f25dabaaed34c4d4bcc44 (diff)
downloadmicheles-20ce686b0193d67ea56823a30551140f88b3aee1.tar.gz
Commited all py papers into Google code
Diffstat (limited to 'pypers/super/super.html')
-rwxr-xr-xpypers/super/super.html564
1 files changed, 564 insertions, 0 deletions
diff --git a/pypers/super/super.html b/pypers/super/super.html
new file mode 100755
index 0000000..a970a18
--- /dev/null
+++ b/pypers/super/super.html
@@ -0,0 +1,564 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.3.4: http://docutils.sourceforge.net/" />
+<title>The truth about super</title>
+<meta name="author" content="Michele Simionato" />
+<meta name="date" content="June 2004" />
+<link rel="stylesheet" href="default.css" type="text/css" />
+</head>
+<body>
+<h1 class="title">The truth about <tt class="literal"><span class="pre">super</span></tt></h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>Michele Simionato</td></tr>
+<tr class="field"><th class="docinfo-name">Email:</th><td class="field-body"><a class="reference" href="mailto:michele.simionato&#64;libero.it">michele.simionato&#64;libero.it</a></td>
+</tr>
+<tr><th class="docinfo-name">Date:</th>
+<td>June 2004</td></tr>
+<tr><th class="docinfo-name">Status:</th>
+<td>Draft</td></tr>
+</tbody>
+</table>
+<div class="document" id="the-truth-about-super">
+<p><tt class="literal"><span class="pre">super</span></tt> is a new built-in, first introduced in Python 2.2 and slightly
+improved and fixed in Python 2.3, which is little known to the average
+Python programmer. One of the reason for this
+fact is its poor documentation`: at the time of this writing
+(June 2004) <tt class="literal"><span class="pre">super</span></tt> documentation is incomplete and in some parts
+misleading and even wrong. For instance, it was recently pointed out
+on comp.lang.python that the standard library (Python 2.3.4, section 2.1)
+still says:</p>
+<pre class="literal-block">
+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.
+</pre>
+<p>The first sentence is just plain wrong. <tt class="literal"><span class="pre">super</span></tt> does not return the
+superclass. There is no such a thing as &quot;the&quot; superclass in a Multiple
+Inheritance (MI) language. 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
+subtle pitfalls of <tt class="literal"><span class="pre">super</span></tt> which are not at all mentioned. IMNSHO
+<tt class="literal"><span class="pre">super</span></tt> is one of the most trickiest and surprising Python constructs,
+so it absolutely needs a document to share light on some of his secrets:
+the present article aims to fix the issues with the current documentation,
+and tell you the &quot;truth&quot; about <tt class="literal"><span class="pre">super</span></tt>. At least the amount of truth
+I have discovered with my experimentations, which is certainly
+not the whole truth ;)</p>
+<p>Here is the plan: first I will discuss the concept of superclass in
+a Multiple Inheritance (MI) world (there is no such a thing as
+&quot;the&quot; superclass!); second, I will show that <tt class="literal"><span class="pre">super</span></tt> is a proxy
+object, able to dispatch to the right methods/attributes in the
+MRO; third,</p>
+<p>recall some background on
+how the resolution of methods works on how
+descriptors work and
+(essentially pointing out to the standard references); then
+I will discuss the more common invocation of <tt class="literal"><span class="pre">super</span></tt> -
+the invocation with two arguments - and finally I will discuss
+the most tricky part, i.e. invoking <tt class="literal"><span class="pre">super</span></tt> with just one
+argument and I will discuss pitfalls.</p>
+<p>Finally, a fair warning: this document is aimed to expert
+Pythonistas. It is not for the faint of heart ;)</p>
+<div class="section" id="first-truth-there-is-no-superclass-in-a-mi-world">
+<h1><a name="first-truth-there-is-no-superclass-in-a-mi-world">First truth: there is no superclass in a MI world</a></h1>
+<p>Readers familiar will single inheritance languages, such as
+Java or Smalltalk, will have a clear concept of superclass
+in mind. This concept, however, has <em>no useful meaning</em> in Python or in
+other Multiple Inheritance languages. This fact was proved to
+me by Bjorn Pettersen in a thread 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:</p>
+<pre class="literal-block">
+ +-----+
+ | T |
+ |a = 0|
+ +-----+
+ / \
+ / \
++-------+ +-------+
+| A | | B |
+| | | a = 2 |
++-------+ +-------+
+ \ /
+ \ /
+ +-----+
+ | C |
+ +-----+
+ :
+ : instantiation
+ c
+</pre>
+<pre class="doctest-block">
+&gt;&gt;&gt; class T(object):
+... a = 0
+</pre>
+<pre class="doctest-block">
+&gt;&gt;&gt; class A(T):
+... pass
+</pre>
+<pre class="doctest-block">
+&gt;&gt;&gt; class B(T):
+... a = 2
+</pre>
+<pre class="doctest-block">
+&gt;&gt;&gt; class C(A,B):
+... pass
+</pre>
+<pre class="doctest-block">
+&gt;&gt;&gt; c = C()
+</pre>
+<p>Who 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. A inherits the attribute 'a' from T,
+so if <tt class="literal"><span class="pre">super(C,c)</span></tt> 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 <tt class="literal"><span class="pre">super(C,c).a</span></tt> would return 0. This
+is NOT what happens. Instead, <tt class="literal"><span class="pre">super(C,c).a</span></tt> walks trought the
+method resolution order <a class="footnote-reference" href="#id4" id="id1" name="id1">[1]</a> of the class of <tt class="literal"><span class="pre">c</span></tt> (which is '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 <tt class="literal"><span class="pre">super(C,c).a</span></tt>
+correctly returns the value 2, not 0:</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; super(C,c).a
+2
+</pre>
+<p>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).</p>
+<p>So, using the word <em>superclass</em> in the standard doc is completely
+misleading and should be avoided altogether.</p>
+</div>
+<div class="section" id="second-truth-super-returns-proxy-objects">
+<h1><a name="second-truth-super-returns-proxy-objects">Second truth: <tt class="literal"><span class="pre">super</span></tt> returns proxy objects</a></h1>
+<p>Having understood that <tt class="literal"><span class="pre">super</span></tt> cannot return and does not return the
+mythical superclass, we ask ourselves what the hell is returning
+<tt class="literal"><span class="pre">super</span></tt> ;) The truth is that <tt class="literal"><span class="pre">super</span></tt> returns proxy objects.
+Informally speaking, a proxy object is an object with
+the ability to dispatch to methods of other classes via delegation.</p>
+<p>Technically, <tt class="literal"><span class="pre">super</span></tt> works by overriding the <tt class="literal"><span class="pre">__getattribute__</span></tt>
+method in such a way that its instances becomes proxy objects providing
+access to the methods in the MRO. The dispatch is done in such a way
+that</p>
+<p><tt class="literal"><span class="pre">super(cls,</span> <span class="pre">instance-or-subclass).meth(*args,</span> <span class="pre">**kw)</span></tt></p>
+<p>corresponds to</p>
+<p><tt class="literal"><span class="pre">&lt;right</span> <span class="pre">method</span> <span class="pre">in</span> <span class="pre">the</span> <span class="pre">MRO&gt;(instance-or-subclass,</span> <span class="pre">*args,</span> <span class="pre">**kw)</span></tt></p>
+<p>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 <em>both cases</em> a bound method is returned (one could naivily
+think, instead, that when a subclass is passed one gets an
+unbound method).</p>
+<p>For instance, in this example</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; class B(object):
+... def __repr__(self):
+... return &quot;&lt;instance of %s&gt;&quot; % self.__class__.__name__
+</pre>
+<pre class="doctest-block">
+&gt;&gt;&gt; class C(B):
+... pass
+</pre>
+<pre class="doctest-block">
+&gt;&gt;&gt; class D(C):
+... pass
+</pre>
+<pre class="doctest-block">
+&gt;&gt;&gt; d = D()
+</pre>
+<p>both</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; print super(C,d).__repr__
+&lt;bound method D.__repr__ of &lt;instance of D&gt;&gt;
+</pre>
+<p>and</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; print super(C,D).__repr__
+&lt;bound method D.__repr__ of &lt;class 'D'&gt;&gt;
+</pre>
+<p>returns bound methods. This means that when I call those methods,
+I get</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; print super(C,d).__repr__()
+&lt;instance of D&gt;
+</pre>
+<p>(here d, a D instance is being passed to <tt class="literal"><span class="pre">__repr__</span></tt>) and</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; print super(C,D).__repr__()
+&lt;instance of type&gt;
+</pre>
+<p>(here D, an instance of the (meta)class <tt class="literal"><span class="pre">type</span></tt> is being passed
+to <tt class="literal"><span class="pre">__repr__</span></tt>).</p>
+<p>Reading the docs,one could think that in order to get unbound methods,
+she needs to switch to the alternative syntax of <tt class="literal"><span class="pre">super</span></tt>, the single
+argument syntax. This is actually completely WRONG.</p>
+</div>
+<div class="section" id="third-truth-the-unbound-syntax-does-not-access-unbound-methods">
+<h1><a name="third-truth-the-unbound-syntax-does-not-access-unbound-methods">Third truth: the 'unbound' syntax does not access unbound methods</a></h1>
+<p>Suppose 'B' has a method called 'meth' like this:</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; B.meth = lambda self :'You called B.meth with first argument %s' % self
+</pre>
+<p>Then <tt class="literal"><span class="pre">B.meth</span></tt> is an unbound method and, mislead by the documentation,
+one could expect to be able to access it with the syntax <tt class="literal"><span class="pre">super(C).meth</span></tt>.
+This is not the case. You get an error instead:</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; super(C).meth
+Traceback (most recent call last):
+ ...
+AttributeError: 'super' object has no attribute 'meth'
+</pre>
+<p>The truth is that 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 <tt class="literal"><span class="pre">super(C)</span></tt> in a super object
+bound to the instance 'd' in this way:</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; boundsuper = super(C).__get__(d, D) # this is the same as super(C,d)
+</pre>
+<p>Now I can access the bound method 'd.meth':</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; print boundsuper.meth
+&lt;bound method D.&lt;lambda&gt; of &lt;instance of D&gt;&gt;
+</pre>
+<p>To really access the unbound method 'D.meth' is tricky; it could be
+done in this way:</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; print boundsuper.meth.__get__(None,D)
+&lt;unbound method D.&lt;lambda&gt;&gt;
+</pre>
+<p>All those tricks requires a good grasp of descriptors (see next
+paragraph). Here I would like just to point out that in my opinion
+having an unbound syntax for descriptors is generating more
+confusion than needed. First of all, there is a problem of poor
+documentation.</p>
+<p>The distinction bound/unbound
+can easily be confused with the distinction between bound and unbound
+methods. So you could expect <tt class="literal"><span class="pre">super(C).meth</span></tt> to be an unbound method
+of the superclass of C (superclass here is intended in some nebolous way).
+This is not that dangerous when you get an error; it is much more
+dangerous when you don't get an error, but you get a result which is
+not what you expect. This happens for special methods which are
+already defined in <tt class="literal"><span class="pre">super</span></tt>.
+For instance <tt class="literal"><span class="pre">super(C).__repr__</span></tt> does not give any error,
+but it is <em>not</em> returning a proxy to <tt class="literal"><span class="pre">D.__repr__</span></tt>, it is
+returning <tt class="literal"><span class="pre">super.__repr__</span></tt> bound to the (unbound) super object <tt class="literal"><span class="pre">super(C)</span></tt>:</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; print super(C).__repr__() # same as repr(super(C))
+&lt;super: &lt;class 'C'&gt;, NULL&gt;
+</pre>
+<p>Very tricky. Notice that <tt class="literal"><span class="pre">super</span></tt> also redefines <tt class="literal"><span class="pre">__new__</span></tt>,
+<tt class="literal"><span class="pre">__init</span></tt>, <tt class="literal"><span class="pre">__get__</span></tt>, <tt class="literal"><span class="pre">__getattribute</span></tt>, as well as inheriting
+other special attributes from <tt class="literal"><span class="pre">object</span></tt>. So you will dispatch to
+these methods in <tt class="literal"><span class="pre">super</span></tt> 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</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; print super(C,C).__repr__()
+&lt;instance of type&gt;
+</pre>
+<p>does the right thing. There is a single use case for the single argument
+syntax of <tt class="literal"><span class="pre">super</span></tt> that I am aware of, but I think it gives more troubles
+than advantages. The use case is the implementation of &quot;autosuper&quot; made
+by Guido on his essay about new-style classes.</p>
+<p>The idea there is to use the unbound super objects as private
+attributes. For instance, in our example, we could define the
+private attribute <tt class="literal"><span class="pre">__sup</span></tt> in the class <tt class="literal"><span class="pre">C</span></tt> as the unbound
+super object <tt class="literal"><span class="pre">super(C)</span></tt>:</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; C._C__sup = super(C)
+</pre>
+<p>With this definition inside the methods the syntax
+<tt class="literal"><span class="pre">self.__sup.meth(arg)</span></tt> can be used
+as an alternative to <tt class="literal"><span class="pre">super(C,</span> <span class="pre">self).meth(arg)</span></tt>, 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 <tt class="literal"><span class="pre">__sup</span></tt> attributes can be hidden
+in a metaclass and made automatic. So, all this seems to work: but
+actually this <em>not</em> the case.
+Things may wrong in various case, for instance for classmethods,
+as in this example:</p>
+<pre class="literal-block">
+#&lt;ex.py&gt;
+
+class B(object):
+ def __repr__(self):
+ return '&lt;instance of %s&gt;' % self.__class__.__name__
+ def meth(self):
+ print &quot;B.meth(%s)&quot; % self
+ meth = classmethod(meth)
+
+class C(B):
+ def meth(self):
+ print &quot;C.meth(%s)&quot; % 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()
+
+#&lt;/ex.py&gt;
+</pre>
+<p>The last line raises an <tt class="literal"><span class="pre">AttributeError:</span> <span class="pre">'super'</span> <span class="pre">object</span> <span class="pre">has</span> <span class="pre">no</span> <span class="pre">attribute</span>
+<span class="pre">'meth'.</span></tt></p>
+<p>So, using a <tt class="literal"><span class="pre">__super</span></tt> unbound super object is not a robust solution
+(notice that everything would work by substituting <tt class="literal"><span class="pre">self.__super.meth()</span></tt>
+with <tt class="literal"><span class="pre">super(C,self).meth()</span></tt>. There are other ways to avoid repeating
+the class name, see for instance my cookbook recipe.</p>
+<p>If it was me, I would just remove the single argument syntax of <tt class="literal"><span class="pre">super</span></tt>,
+making it illegal. But this would probably break someone code, so
+I don't think it will ever happen. Another solution would be just to
+deprecate it. There is no need for this syntax, one can always circumvent it.</p>
+</div>
+<div class="section" id="forth-truth-super-returns-descriptor-objects">
+<h1><a name="forth-truth-super-returns-descriptor-objects">Forth truth: <tt class="literal"><span class="pre">super</span></tt> returns descriptor objects</a></h1>
+<p>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. <a class="footnote-reference" href="#id6" id="id2" name="id2">[2]</a> 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 <a class="footnote-reference" href="#id7" id="id3" name="id3">[3]</a>. You should read it before continuing this article,
+since it explains all the details. However, for the sake of our discussion
+of <tt class="literal"><span class="pre">super</span></tt>, it is enough to say that a <em>descriptor class</em> is just a
+regular new-style class which implements a .``__get__`` method with
+signature <tt class="literal"><span class="pre">__get__(self,</span> <span class="pre">obj,</span> <span class="pre">objtyp</span> <span class="pre">=</span> <span class="pre">None)</span></tt>. A <em>descriptor object</em>
+is just an instance of a descriptor class.</p>
+<p>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 <tt class="literal"><span class="pre">C.descr</span></tt> is actually implemented by Python as a
+call to <tt class="literal"><span class="pre">descr.__get__(None,</span> <span class="pre">C)</span></tt>, whereas the same syntax for an
+instance of C corresponds to a call to <tt class="literal"><span class="pre">descr.__get__(c,</span> <span class="pre">type(c))</span></tt>.</p>
+<p>This explanation is relevant in order to understand how the <tt class="literal"><span class="pre">super</span></tt>
+built-in works when it is called with only one argument, i.e. in the
+unbound form. In this case <tt class="literal"><span class="pre">super(C)</span></tt> returns a descriptor which
+is intended to be used as an attribute in other classes. This is
+an example:</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; class D(C):
+... sup = super(C)
+</pre>
+<pre class="doctest-block">
+&gt;&gt;&gt; d = D()
+&gt;&gt;&gt; d.sup.a
+2
+</pre>
+<p>This works since <tt class="literal"><span class="pre">d.sup.a</span></tt> calls</p>
+<table class="footnote" frame="void" id="id4" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1" name="id4">[1]</a></td><td>Descriptors gives an enormous power to the application
+programmer, especially when combined with metaclasses. For instance,
+using descriptors I did implement a prototype-based object system for
+Python in few lines: see of course this was an hack, only useful as proof
+of concept.</td></tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="fifth-truth-super-does-not-work-with-meta-attributes">
+<h1><a name="fifth-truth-super-does-not-work-with-meta-attributes">Fifth truth: <tt class="literal"><span class="pre">super</span></tt> does not work with meta-attributes</a></h1>
+<p>If you start using <tt class="literal"><span class="pre">super</span></tt> intensively, soon or latter you will find
+a number of subtilities. One of these is the fact that <tt class="literal"><span class="pre">super</span></tt> does not
+work well with the <tt class="literal"><span class="pre">__name__</span></tt> special attribute. Consider this example:</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; class B(object):
+... &quot;This is class B&quot;
+...
+&gt;&gt;&gt; class C(B):
+... pass
+...
+</pre>
+<p>Here the special class attribute <tt class="literal"><span class="pre">__doc__</span></tt> is retrieved as you would expect:</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; super(C,C).__doc__ == super(C,C()).__doc__ == B.__doc__
+True
+</pre>
+<p>On the other hand, the special attribute <tt class="literal"><span class="pre">__name__</span></tt> is not
+retrieved correctly:</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; super(C,C).__name__ # one would expect it to be 'B'
+Traceback (most recent call last):
+ File &quot;&lt;stdin&gt;&quot;, line 1, in ?
+AttributeError: 'super' object has no attribute '__name__'
+</pre>
+<p>The problem is that <tt class="literal"><span class="pre">__name__</span></tt> is not just a plain class
+attribute: it is actually a &quot;getset descriptor&quot; defined on
+the metaclass &quot;type&quot; (try to run <tt class="literal"><span class="pre">help(type.__dict__['__name__'])</span></tt>
+and you will see for yourself). More in general, <tt class="literal"><span class="pre">super</span></tt> 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 <a class="footnote-reference" href="#id8" id="id5" name="id5">[4]</a>: here I am only interested
+to the issues with <tt class="literal"><span class="pre">super</span></tt>. Consider this example:</p>
+<p>#&lt;example1.py&gt;</p>
+<dl>
+<dt>class M(type):</dt>
+<dd>&quot;A metaclass with a class attribute 'a'.&quot;
+a = 1</dd>
+<dt>class B:</dt>
+<dd>&quot;An instance of M with a meta-attribute 'a'.&quot;
+__metaclass__ = M</dd>
+<dt>class C(B):</dt>
+<dd>&quot;An instance of M with the same meta-attribute 'a'&quot;</dd>
+<dt>if __name__ == &quot;__main__&quot;:</dt>
+<dd>print B.a, C.a # =&gt; 1 1
+print super(C,C).a #=&gt; attribute error</dd>
+</dl>
+<p>#&lt;/example1.py&gt;</p>
+<p>If you run this, you will get an attribute error. This is a case
+where <tt class="literal"><span class="pre">super</span></tt> is doing the <em>right</em> thing, since 'a' is <em>not</em> 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 <em>not</em> in the MRO of C. A similar thing happens for the &quot;__name__&quot;
+attribute (the fact that it is a descriptor and not a plain
+attribute does not matter), so <tt class="literal"><span class="pre">super</span></tt> is working correctly, but
+still it may seems surprising at first.</p>
+</div>
+<div class="section" id="the-final-truth-there-are-other-bugs-and-pitfalls">
+<h1><a name="the-final-truth-there-are-other-bugs-and-pitfalls">The final truth: there are other bugs and pitfalls</a></h1>
+<p>There are various <tt class="literal"><span class="pre">super</span></tt> pitfalls currently undocumented and
+that experienced Python programmers should be aware of.</p>
+<p>The unbound form of <tt class="literal"><span class="pre">super</span></tt> does not play well with pydoc.
+The problems is still there in Python 2.3.4 (see bug report SF729103)</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; class B(object): pass
+...
+&gt;&gt;&gt; class C:
+... s=super(B)
+...
+&gt;&gt;&gt; help(C)
+Traceback (most recent call last):
+ ...
+ ... lots of stuff here
+ ...
+File &quot;/usr/lib/python2.3/pydoc.py&quot;, line 1198, in docother
+ chop = maxlen - len(line)
+TypeError: unsupported operand type(s) for -: 'classobj' and 'int'
+</pre>
+<p>I have not yet clear what the cause is, but it is certainly quite
+tricky.</p>
+<p>There is also another subtle pitfall which is not directly related
+to <tt class="literal"><span class="pre">super</span></tt> but which is often encountered working with <tt class="literal"><span class="pre">super</span></tt>.
+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</p>
+<p><tt class="literal"><span class="pre">super(MyCls,</span> <span class="pre">self).__getitem__(5)</span></tt></p>
+<p>works, but not</p>
+<p><tt class="literal"><span class="pre">super(MyCls,</span> <span class="pre">self)[5]</span></tt>.</p>
+<p>The problem is general to all special methods, not only to <tt class="literal"><span class="pre">__getitem__</span></tt>,
+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 Hetting as a comment to the bug report SF805304.
+Shortly put, this is not a problem of <tt class="literal"><span class="pre">super</span></tt> per se, the problem is
+that (using <tt class="literal"><span class="pre">__getitem__</span></tt> as example)</p>
+<blockquote>
+<tt class="literal"><span class="pre">x[5]</span> <span class="pre">==</span> <span class="pre">type(x).__getitem__(x,5)</span></tt></blockquote>
+<p><em>only if</em> <tt class="literal"><span class="pre">__getitem__</span></tt> is explicitely defined in <tt class="literal"><span class="pre">type(x)</span></tt>. If
+<tt class="literal"><span class="pre">type(x)</span></tt> does not define <tt class="literal"><span class="pre">__getitem__</span></tt> directly, but only
+indirectly via delegation (i.e. overriding <tt class="literal"><span class="pre">__getattribute__</span></tt>),
+then the second form works but not the first one, i.e. the <tt class="literal"><span class="pre">[]</span></tt> syntax
+is not automatically converted to the second form, the working one.</p>
+<p>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 <tt class="literal"><span class="pre">[]</span></tt> call, the <tt class="literal"><span class="pre">iter</span></tt> call, the <tt class="literal"><span class="pre">repr</span></tt> call, etc. etc.)
+are special and bypass <tt class="literal"><span class="pre">__getattribute__</span></tt>. Guido advice is:
+just use the more explicit form and everything will work.</p>
+<p>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).</p>
+</div>
+<div class="section" id="the-final-truth-when-it-comes-to-super-don-t-trust-even-guido-himself">
+<h1><a name="the-final-truth-when-it-comes-to-super-don-t-trust-even-guido-himself">The final truth: when it comes to <tt class="literal"><span class="pre">super</span></tt> don't trust even Guido himself!</a></h1>
+<p>In order to explain how <tt class="literal"><span class="pre">super</span></tt> works, Guido describes a
+&quot;fully functional implementation of the super() built-in class in
+pure Python&quot; in &quot;Unifying types and classes in Python 2.2&quot;.
+Unfortunately, that implemenentation is more harmful than helpful, since
+the current <tt class="literal"><span class="pre">super</span></tt> DOES NOT work in the same way :-(
+Take for instance this example:</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; class C(object):
+... f='C.f'
+</pre>
+<pre class="doctest-block">
+&gt;&gt;&gt; class D(C):
+... f='D.f'
+</pre>
+<p>Here the <tt class="literal"><span class="pre">super</span></tt> works fine,
+df</p>
+<pre class="doctest-block">
+&gt;&gt;&gt; print super(D,D()).f
+C.f
+</pre>
+<p>but the class <tt class="literal"><span class="pre">Super</span></tt> described by Guido will raise an attribute
+error when invoked as <tt class="literal"><span class="pre">Super(D,D()).f</span></tt>. Therefore Super is NOT
+equivalent to the currently implemented <tt class="literal"><span class="pre">super</span></tt> built-in</p>
+</div>
+<div class="section" id="notes">
+<h1><a name="notes">Notes</a></h1>
+<table class="footnote" frame="void" id="id6" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id2" name="id6">[2]</a></td><td>I wrote an essay on Python 2.3 Method Resolution Order which
+you may find here:</td></tr>
+</tbody>
+</table>
+<table class="footnote" frame="void" id="id7" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id3" name="id7">[3]</a></td><td>Raymond Hetting wrote a beautiful essay on descriptors here:</td></tr>
+</tbody>
+</table>
+<table class="footnote" frame="void" id="id8" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id5" name="id8">[4]</a></td><td>David Mertz and me wrote a couple of articles on metaclasses;
+the second one is the relevant one for the issues discussed here:</td></tr>
+</tbody>
+</table>
+<table class="footnote" frame="void" id="id9" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="id9">[5]</a></td><td><a class="reference" href="http://groups.google.it/groups?hl=it&amp;lr=&amp;ie=UTF-8&amp;threadm=2259b0e2.0304300625.4e0ebace%40posting.google.com&amp;rnum=3&amp;prev=/groups%3Fhl%3Dit%26lr%3D%26ie%3DUTF-8%26q%3Dsimionato%2Bpettersen%2Bsuper%26btnG%3DCerca%26meta%3Dgroup%253Dcomp.lang.python">http://groups.google.it/groups?hl=it&amp;lr=&amp;ie=UTF-8&amp;threadm=2259b0e2.0304300625.4e0ebace%40posting.google.com&amp;rnum=3&amp;prev=/groups%3Fhl%3Dit%26lr%3D%26ie%3DUTF-8%26q%3Dsimionato%2Bpettersen%2Bsuper%26btnG%3DCerca%26meta%3Dgroup%253Dcomp.lang.python</a>.*</td></tr>
+</tbody>
+</table>
+</div>
+</div>
+<hr class="footer" />
+<div class="footer">
+<a class="reference" href="super.txt">View document source</a>.
+Generated on: 2004-06-13 20:23 UTC.
+Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+</div>
+</body>
+</html>