[Tutor] difference between super() and parent.__init__()?

Steven D'Aprano steve at pearwood.info
Sat Oct 22 08:16:52 CEST 2011


Alex Hall wrote:
> On 10/21/11, Steven D'Aprano <steve at pearwood.info> wrote:
[...]
>> The one exception to this is if your class changes the method signature.
>> E.g. if A.method takes no arguments, but B.method requires an argument.
>> super cannot help you now. But changing the signature of methods is
>> almost always the wrong thing to do: it is a violation of good object
>> oriented design, and should be avoided. The main time it is justified is
>> in the class constructor methods, __new__ or __init__, in which case you
>> may need to avoid super and *carefully* manage the inheritance by hand.

> I'm not sure about this part. Could I not simply do something like:
> class a(object):
>  def m(self, p1): pass
> 
> class b(a):
>  def m(self, p1, p2, *args, **kwords):
>   super(b, self).m(*args, **kwords) #different signatures, but a.m()
> still gets what it wants, if called correctly

No, that won't work. Consider what happens when you do this:


instance = b()
instance.m(1, 2, "spam", "ham", foo=None)

The m method gets called with arguments:

p1 = 1
p2 = 2
args = ("spam", "ham")
kwords = {"foo": None}


So far so good. But b.m calls a.m using:

super(b, self).m(*args, **kwords)

which drops p1=1 completely, replacing it with "spam". That surely is 
incorrect. It also tries to supply an extra two arguments, "ham" and 
foo=None, but a.m only takes one argument.


> Also, what is the difference between __init__ (what I always use) and
> __new__? If you can change these, why not other methods? Of course
> these would be the most commonly changed, but the question stands.

__new__ and __init__ are respectively the constructor and initialiser 
for the class.

__new__ is responsible for actually creating the instance, and returning 
it. If the class is immutable, like int, str or tuple, this is the time 
to set the contents of the instance. (Once the instance is created, it's 
too late to change it.) Normally, you don't need to do anything with 
__new__, you can consider it a moderately specialised method.

__init__ is responsible for initialising any extra attributes on the 
instance, or for mutable classes like lists or dicts, setting the 
contents. It's much more common to use __init__ rather than __new__.


-- 
Steven



More information about the Tutor mailing list