Issue5229
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.
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) | 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) * | 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) | 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) * | Date: 2009-02-16 22:43 | |
Fixed in r69703 |
|||
msg82281 - (view) | Author: Daniel Stutzbach (stutzbach) | 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) * | 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) * | 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) * | Date: 2009-02-25 20:10 | |
See: http://docs.python.org/dev/library/functions.html#super |
|||
msg82726 - (view) | Author: Daniel Stutzbach (stutzbach) | 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) * | 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) | 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) | 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) * | 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:45 | admin | set | github: 49479 |
2009-02-25 23:54:53 | rhettinger | set | messages: + msg82733 |
2009-02-25 23:48:16 | stutzbach | set | messages: + msg82732 |
2009-02-25 23:33:27 | stutzbach | set | messages: + msg82731 |
2009-02-25 23:16:21 | rhettinger | set | messages: + msg82729 |
2009-02-25 22:34:24 | stutzbach | set | messages: + msg82726 |
2009-02-25 20:10:03 | rhettinger | set | messages: + msg82715 |
2009-02-25 20:09:23 | rhettinger | set | messages: + msg82714 |
2009-02-16 23:39:34 | rhettinger | set | messages: + msg82283 |
2009-02-16 23:13:34 | stutzbach | set | messages: + msg82281 |
2009-02-16 22:43:14 | rhettinger | set | status: open -> closed resolution: fixed messages: + msg82278 |
2009-02-12 22:18:31 | stutzbach | set | messages: + msg81829 |
2009-02-12 22:05:43 | rhettinger | set | priority: low assignee: georg.brandl -> rhettinger messages: + msg81826 nosy: + rhettinger |
2009-02-12 20:39:02 | LambertDW | set | nosy: + LambertDW |
2009-02-12 19:24:04 | stutzbach | create |