This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Documentation for super() neglects to say what super() actually does
Type: Stage:
Components: Documentation Versions: Python 3.0, Python 3.1, Python 2.7, Python 2.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: rhettinger Nosy List: LambertDW, georg.brandl, rhettinger, stutzbach
Priority: low Keywords:

Created on 2009-02-12 19:24 by stutzbach, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (13)
msg81804 - (view) Author: Daniel Stutzbach (stutzbach) (Python committer) Date: 2009-02-12 19:24
The documentation for super() describes the arguments that can be passed
to super(), use cases for super(), an example, and caveats about what
cannot be done with the returned object.  However, the documentation
neglects to mention what super() actually *does*, except for the
circular definition in the first line: "Return a super object that acts
as a proxy to superclasses of type."

Worse still, the definition in the first line is incorrect, since it may
proxy any type in the type hierarchy (not necessarily a superclass).

I found this webpage helpful for understanding what super() actually
does: http://fuhm.net/super-harmful/

I would submit a suggested improvement to the documentation, but I do
not really understand what super() does when the second argument is
omitted or a class.
msg81826 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2009-02-12 22:05
I will work on this a bit more.

Keep in mind that it will be hard to please the author of that article,
as he finds the whole notion of multiple inheritance to be bankrupt.
msg81829 - (view) Author: Daniel Stutzbach (stutzbach) (Python committer) Date: 2009-02-12 22:18
Yes, by citing that article I don't mean to endorse its opinions. 
Regrettably, it's the best documentation on super() I could find (in an
admittedly quick search).

Any improvements efforts you make to improve the existing super()
documentation would much appreciated.
msg82278 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2009-02-16 22:43
Fixed in r69703
msg82281 - (view) Author: Daniel Stutzbach (stutzbach) (Python committer) Date: 2009-02-16 23:13
The new text is still inaccurate.  It reads in part "Return a proxy
object that delegates method calls to a parent class of type".  However,
this is not necessarily true.  Consider the following example of
diamond-inheritance, where we have a common Ancestor class that has two
children (Sibling1 and Sibling2), and a class that inherits from both
siblings (Child).

Child's call to super() returns a proxy for Sibling1's methods, as
described.  However, Sibling1's call to super() returns a proxy for
Sibling2's methods, even though Sibling2 is not Sibling1's parent.

Perhaps add some text stating something to the effect of:  If
object-or-type is an object returned by a previous call to super(), a
new proxy is returned for the next class in the hierarchy.  By
repeatedly calling super(), all the classes in the hierarchy can be
accessed.  Since a parent class's methods will often be accessed by a
proxy object, calling super() in a parent class will result in a proxy
for the next class in the object's class hierarchy which may have no
direct relationship to the parent class itself.

(Undoubtedly, it could be worded better, though)

>>> class Ancestor(object):
...   def foo(self):
...      print 'Ancestor.foo'
...
>>> class Sibling1(Ancestor):
...   def foo(self):
...     super(Sibling1, self).foo()
...     print 'Sibling1.foo'
...
>>> class Sibling2(Ancestor):
...   def foo(self):
...     super(Sibling2, self).foo()
...     print 'Sibling2.foo'
...
>>> class Child(Sibling1,Sibling2):
...   def foo(self):
...     super(Child, self).foo()
...     print 'Child.foo'
...
>>> x = Child()
>>> x.foo()
Ancestor.foo
Sibling2.foo
Sibling1.foo
Child.foo
msg82283 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2009-02-16 23:39
I'm happy with the current wording.  Attempts to over-explain will make
it harder to understand.  The term "parent" is used loosely to mean one
of the preceding classes in the inheritance diagram except for the class
of the caller.  To make that interpretation clearer, the next sentence
specifically references the __mro__ attribute.  Further explanations of
search-order and multiple inheritance should be done somewhere else.   
The docs for super() are not are the right place to cover all aspects of
multiple inheritance.

In the case of single inheritance, the term "parent" is exactly correct.
 In the case of multiple inheritance, the notion of "parent" becomes
that-which-precedes-self-in-the-dynamically-computed-search-order.  IMO,
the loose use of "parent" is appropriate in a first sentence. 
Otherwise, the whole doc entry becomes incomprehensible from the start.  

If someone adds a fuller explanation of multiple-inheritance to the
docs, I would be happy to link to it but I don't want to make the docs
for super() any more inpenatrable that they already are.
msg82714 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2009-02-25 20:09
FWIW, I did a further update to the super docs to clarify that parent
classes are search in single inheritance models and that both parent and
siblings are searched in multiple inheritance models.  Made the concept
more concrete by relating pointing to the __mro__ attribute and by
comparing it to getattr() which also uses the __mro__.
msg82715 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2009-02-25 20:10
See:  http://docs.python.org/dev/library/functions.html#super
msg82726 - (view) Author: Daniel Stutzbach (stutzbach) (Python committer) Date: 2009-02-25 22:34
Thanks!  These improvements are very helpful.  The one missing notion is
that "object-or-type" may be a proxy object, in which case super()
returns a new proxy that additionally skips "type".

Perhaps add the following sentence to the end of the first paragraph:
"If *object-or-type* is a proxy object, *super* returns a new proxy that
additionally skips *type*."

Also, I just spotted a typo.  In the following sentence, "in" should be
"it": "This makes in possible to implement “diamond diagrams” where
multiple base classes implement the same method"

Thanks, again!
msg82729 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2009-02-25 23:16
> Perhaps add the following sentence to the end of 
> the first paragraph: "If *object-or-type* is a proxy
>  object, *super* returns a new proxy that additionally
> skips *type*."

I'm not really sure what that even means.  Nor do I think
it was one of the use cases that Guido had in mind or is
tested in the unittest suite.

Is this something that has to be covered in the super() docs?
It seems like an implementation side-effect.
msg82731 - (view) Author: Daniel Stutzbach (stutzbach) (Python committer) Date: 2009-02-25 23:33
Actually, it's essential to how super() works.  Here's an example using
single inheritance:

class A(object):
  def foo(self):
    print 'A'

class B(object):
  def foo(self):
    super(B, self).foo()
    print 'B'

class C(object):
  def foo(self):
    super(C, self).foo()
    print 'C'

x = C()
x.foo()

The "super" in x.foo() return a proxy for x that skips C.  
Next, we call foo() on that proxy, which calls B's foo().

In B's foo(), "self" is the proxy.  B's foo() passes the proxy to
super(), returning a new proxy for x that skips C and B.  Finally, we
call foo() on the new proxy, which calls A's foo().
msg82732 - (view) Author: Daniel Stutzbach (stutzbach) (Python committer) Date: 2009-02-25 23:48
In the previous example, I meant to type

class B(A)

and

class C(B)

rather than having them all derive from object.  That's what I get for
not actually testing the code. ;-)
msg82733 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2009-02-25 23:54
I see what you mean but think that the docs shouldn't go into how
super() is implemented.  Already, they've reached an information density
such that adding more explanations will make it collectively less clear.
 As soon as you mention proxy objects as inputs, I'm pretty sure that
you've lost most of your readers (including me).  

I think what we've got is enough to help folks begin to understand what
to do even if they can't describe how super() is implemented.
History
Date User Action Args
2022-04-11 14:56:45adminsetgithub: 49479
2009-02-25 23:54:53rhettingersetmessages: + msg82733
2009-02-25 23:48:16stutzbachsetmessages: + msg82732
2009-02-25 23:33:27stutzbachsetmessages: + msg82731
2009-02-25 23:16:21rhettingersetmessages: + msg82729
2009-02-25 22:34:24stutzbachsetmessages: + msg82726
2009-02-25 20:10:03rhettingersetmessages: + msg82715
2009-02-25 20:09:23rhettingersetmessages: + msg82714
2009-02-16 23:39:34rhettingersetmessages: + msg82283
2009-02-16 23:13:34stutzbachsetmessages: + msg82281
2009-02-16 22:43:14rhettingersetstatus: open -> closed
resolution: fixed
messages: + msg82278
2009-02-12 22:18:31stutzbachsetmessages: + msg81829
2009-02-12 22:05:43rhettingersetpriority: low
assignee: georg.brandl -> rhettinger
messages: + msg81826
nosy: + rhettinger
2009-02-12 20:39:02LambertDWsetnosy: + LambertDW
2009-02-12 19:24:04stutzbachcreate