6
class A:
    def __init__(self):
        print 'A'


class B(A):
    def __init__(self):
        print 'B'


b = B()
B

In C++, I would have expected to see A B output, but in Python I am getting only B. I know that I can do super(B, self).__init__() to achieve the same in Python, but as this is apparently not the default (or is it - I am new to the syntax as well), I am worried that the paradigms for instatinating objects are completely different.

So what are objects in Python, what is their relation with classes and what is the standard way to initialize all data in all parent classes in Python?

William Pursell
  • 204,365
  • 48
  • 270
  • 300
Vorac
  • 8,726
  • 11
  • 58
  • 101

3 Answers3

7

Python rarely does anything automatically. As you say, if you want to invoke the superclass __init__, then you need to do it yourself, usually by calling super:

class B(A):
    def __init__(self):
        print 'B'
        super(B, self).__init__()

The point to note is that instance attributes, like everything else in Python, are dynamic. __init__ is not the constructor, that's __new__ which you rarely need to meddle with. The object is fully constructed by the time __init__ is called, but since instance attributes are dynamic they are usually added by that method, which is only special in that it's called first once the object is created.

You can of course create instance attributes in any other method, or even from outside the class itself by simply doing something like myBobj.foo = 'bar'.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • 1
    `super()` only works for new-style classes, so your code will only work if `A` is declared `class A(object):`. In the OP's code it's just `class A:`. Also, to avoid hardcoding names in subclasses, I prefer to write `super(self.__class__, self).__init__()` which will work regardless of what the subclass is named. – martineau Jun 12 '13 at 11:25
  • 2
    @martineau don't *ever* do that, it is fundamentally broken. In a chain of inheritance, `self.__class__` always refers to the bottom-most class: if you call super on `self.__class__` in the middle of a chain, it will refer to the parent of the bottom subclass, and will therefore get stuck in an endless cycle. – Daniel Roseman Jun 12 '13 at 11:36
  • Good point. So there's no good way to avoid using the subclass's actual name in a `super()` call? – martineau Jun 12 '13 at 12:23
  • @martineau There is not. The usage of super is actually controversial in python for other reasons. You're really better off making the call to the parent explicitly rather than with super. – sage88 Aug 24 '16 at 20:58
4

So what are objects in Python

Well, objects in python are like dictionaries of members and methods. It's no more sophisticated than that. You don't have visibility handling (if you want to hide a member, just do not talk about it in the public documentation, only with a comment).

what is their relation with classes

A class defines the method/member skeleton that will instantiate that dict/object. So you got the constructor __init__(), which is only a handler used when you create that object.

what is the standard way to initialize all data in all parent classes in Python?

Either you do not redefine the constructor, and then all parent classes will have their constructor initiated (like the default C++ behavior) or you do redefine the constructor, and then have to make an explicit call to your parent class's constructor.

Remember the zen of python: "Explicit is better than implicit". It totally applies here.

zmo
  • 24,463
  • 4
  • 54
  • 90
3

You need to invoke the base constructor in your inherited class constructor:

class B(A):
    def __init__(self):
        A.__init__(self)
        # super(B, self).__init__() you can use this line as well
        print 'B'
Konstantin Dinev
  • 34,219
  • 14
  • 75
  • 100