summaryrefslogtreecommitdiff
path: root/pypers/super/super.html
blob: a970a18480ffa5b722ff00c73d96817f28224a52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
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>