[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