5

Why don't I ever see the following in Python code?

class A:
    def __init__(self, ...):
        # something important

class B(A):
    __init__ = A.__init__

It seems to work on my box with Python 2.5, 2.6, 2.7, and PyPy 1.8.

I see the following a lot, instead:

class B(A):
    def __init__(self, *args, **kwargs):
        A.__init__(self, *args, **kwargs)

or something using super.

I like my first example better (explicit is better than implicit!) but I'm worried that it's not kosher for some reason. Is there something wrong or bad with it?

EDIT: Yep, I meant A.__init__, not self.__init__

Chris Morgan
  • 86,207
  • 24
  • 208
  • 215
ligfx
  • 446
  • 2
  • 8
  • 1
    I don't see how `__init__ = self.__init__` would do anything in this context. `self` is not a keyword in Python. – omz May 23 '12 at 22:16
  • I think, perhaps `__init__ = A.__init__`? –  May 23 '12 at 22:17
  • 6
    Is there any reason to bother? The parent class's constructor will be inherited if you don't declare one in your subclass. You only need to override it if you're doing something extra. – Blckknght May 23 '12 at 22:18
  • If you are seeing that construct (ie. without extra code in the `__init__`) I would suspect the code was written by someone inexperienced in Python and used to doing such things in another language – John La Rooy May 23 '12 at 22:23
  • @gnibbler Or it could be a stub. I can't think of a language where you would have to override methods in subclasses that don't do anything but calling super. – omz May 23 '12 at 22:34
  • Woops, yep, it should be `A.__init__`, my b – ligfx May 23 '12 at 22:37

1 Answers1

11

Sure, it'll work (assuming you get it right, which it is not in your example), but there's no reason to do it. If you want B to call A's __init__(), just don't define __init__() on B and that'll happen automatically. That's the whole point of inheritance, after all.

The only reason you'd ever want to write an __init__() for B is if you wanted to do something when initializing a B instance in addition to what is done to initialize an A instance. In that case you'd write additional code besides just calling A.__init__(), so a simple assignment wouldn't suit there, either.

I suppose you could use this if you wanted to protect B's __init__() from being changed by a monkey-patch to A. But that seems like rather an edge case. Worse, it's unexpected behavior and a blatant denial of Python's dynamic nature.

kindall
  • 178,883
  • 35
  • 278
  • 309
  • "protect ... monkey-patch" Except that it wouldn't do that, since the lookup is done at runtime, not compile time. – Ignacio Vazquez-Abrams May 23 '12 at 22:26
  • But the class definition will happen at runtime too. It's just a matter of what happens first: the only patches to class A which affect class B in such a case are the patches that are applied before class B is loaded, which will be probably be none if they are in the same module. – Dietrich Epp May 23 '12 at 22:39
  • You're right, it does invoke the superclass's `__init__` method by default. I never realized this, because I always see code like my second example—why do people write it like that, then? (for example, http://stackoverflow.com/questions/6535832/python-inherit-the-superclass-init) – ligfx May 23 '12 at 22:39
  • @MichaelMaltese: I think that was intended as an example, with other contents omitted which would not be in real life. It was just there to highlight his point. – Chris Morgan May 23 '12 at 22:45
  • 1
    @ChrisMorgan I see real-life code like that a lot, though. I guess it's just bad code that's been copied around. – ligfx May 23 '12 at 22:46
  • 1
    @MichaelMaltese: I've seen real code like that occasionally, too. It's bad. – Chris Morgan May 23 '12 at 22:47
  • It might be worth noting that `super` behaves differently, by [walking through the MRO](www.artima.com/weblogs/viewpost.jsp?thread=236275#there-is-no-superclass-in-a-mi-world), and may not always directly call A.__init__. – Casey Kuball May 24 '12 at 01:02