On Jul 31, 11:16 am, Ian Kelly <ian.g.ke...@gmail.com> wrote: > On Sat, Jul 31, 2010 at 4:22 AM, Steven D'Aprano > > > > <st...@remove-this-cybersource.com.au> wrote: > > On Fri, 30 Jul 2010 21:40:21 -0600, Ian Kelly wrote: > > >> I have to chime in and agree that the name "super" is problematic. I'm > >> reading this thread with a sense of alarm because I apparently never > >> read the super() documentation too closely (why would I? "Oh, it just > >> accesses an attribute from a superclass. Moving on.") and have been > >> writing code for the past four years under the impression that super() > >> will always refer to a superclass of the current class. > > > In Python 2.x, super() doesn't know what the current class is. You have > > to explicitly tell it. If you tell it a lie, surprising things will > > happen. > > > Assuming you accurately tell it the current class, can you give an > > example where super() doesn't refer to a superclass of the current class? > > Brian gave a good example, so I refer you to that. > > > > >> On a tangent, is it just me, or is the super() documentation incorrect, > >> or at least unclear? Quoting from the first two paragraphs: > > > Yes, it's a bit unclear, because it's a complex function for dealing with > > a complicated situation. But if you have single inheritance, it's simple. > > Anywhere you would write > > > class C(B): > > def method(self, *args): > > B.method(*args) > > > you can write > > > class C(B): > > def method(self, *args): > > super(C, self).method(*args) > > > and it will Just Work. > > Until somebody else comes along and creates class E that inherits from > both C and D and also uses super(), and now suddenly the super() call > in C becomes equivalent to "D.method(*args)" instead for instances of > E, potentially with unexpected results. Or worse, E.method > incorrectly calls both C.method and D.method explicitly, and now > D.method gets invoked twice, once implicitly from C.method, and once > explicitly from E.method. > > I realize that it is the responsibility of the person writing class E > to make sure they're working with class C correctly, but in order for > them to do that, ultimately every method in class C should be > documented as to whether it calls super() or not, and if so whether it > is designed only for single inheritance or with the MRO in mind. That > really shouldn't be necessary,
I was with you up to here. It's *manifestly* necessary. One cannot inherit from a class reliably without knowing how it's implemented. Knowing the interface is not enough. This is not limited to multiple inheritance; it happens with single inheritance as well, just less often. It's not limited to Python, this is true of Java, C++, and every other OOP language I know of. Take list. Say you want a singly inherit from list to implement some kind of observer that emits a signal every time an item is set. How do you do it? You can't tell by looking at the interface. Do you only have to override __setattr__? Or do you also have to override other methods (insert, append, etc)? That depends on whether insert et al. call __setattr__ or operate at a lower level. You can't tell simply by looking at the interface. You have to have knowledge of the internals of list. It's the same problem with multiple inheritance, only exacerbated. The issues with super is a new dimension, but it's the same problem: you have to know what you're inheriting from. This is a fundamental issue with all inheritance. The problem, in my mind, is that people use inheritance for stuff that doesn't need it. class MyFoo(SomebodyElsesFoo): def my_tacked_on_method(self): self.call_this_method() self.then_call_that_method() Unnecessary and risky. Do this: my_tacked_on_function(foo): foo.call_this_method() foo.then_call_that_method() The only reason to inherit in a situation like this is if you need polymorphism (you want to pass your MyFoo to a function that operates on objects that define a my_tacked_on_method). A lot Michele Simionato's objections to inheritance are based on the idea that you don't necessarily know what you're inheriting from. I say, if you don't know what you're inheriting from, you shouldn't be inheriting. I say this as a strong proponent of inheritance and multiple inheritance in particular. I believe it's the best way in general for objects of different types to share large portions of their behavior. But it has its place. When you have a class you that don't anything about the implementation of, that is NOT the place for inheritance. In that case you should either use composition, or learn what it is you're inheriting from and take responsibility if the owner changes it. Or just don't try to share behavior. My view of inheritance is a lot like the orthodox Catholic view of sex. To Catholics, sex between married people is a wonderful, holy thing. To me, inheriting from classes you know the implementation of is a wonderful, holy thing. But, sex outside of marriage, and inheriting from classes you don't know, is deadly sin and you will burn in Hell. > and in my current view from a > maintenance perspective, best practice is to only use super() in the > multiple-inheritance scenarios it was specifically designed for I use super() exclusively for all types of inheritance, unless I'm inheriting from a class I know uses old form (which is none of mine, and I only rarely inherit from classes I don't own). Carl Banks -- http://mail.python.org/mailman/listinfo/python-list