3

I'm learning Python and I've found something about how Python constructs a sub class which confuses me.

I have a class that inherits from the list class as follows.

class foo(list):
    def __init__(self, a_bar):
        list.__init__([])
        self.bar = a_bar

I know that list.__init__([]) needs to be there but I'm confused about it. It seems to me that this line will just create a new list object and then assign it to nothing, so I would suspect that it would just get garbage collected. How does Python know that this list is part of my object? I suspect that there is something happening behind the scenes and I'd like to know what it is.

1
  • 3
    Where did you find this code? It's incorrect Commented Jul 28, 2012 at 18:27

4 Answers 4

3

The multiple-inheritance-safe way of doing it is:

class foo(list):
    def __init__(self, a_bar):
        super(foo, self).__init__()
        ...

which, perhaps, makes it clearer that you're calling the baseclass ctor.

Sign up to request clarification or add additional context in comments.

2 Comments

It needs a bit more than that to be MI-safe.
Such as all classes in the inheritance tree agreeing on __init__ arguments using super. See Python's super() considered super!.
2

You usually do this when subclassing and overriding the __init__() function:

list.__init__(self)

If you're using Python 3, you can make use of super():

super().__init__()

Comments

1

The actual object is not created with __init__ but with __new__. __init__ is not for creating the object itself but for initializing it --- that is, adding attributes, etc. By the time __init__ is called, __new__ has already been called, so in your example the list was already created before your code even runs. __init__ shouldn't return anything because it's supposed to initialize the object "in-place" (by mutating it), so it works by side-effects. (See a previous question and the documentation.)

Comments

1

You're partly right:

list.__init__([]) 

"creates a new list object." But this code is wrong. The correct code _should_be:

list.__init__(self)

The reason you need it to be there is because you're inheriting from a list that has it's own __init__() method where it (presumably) does important to initialize itself. When you define your own __init__() method, you're effectively overriding the inherited method of the same name. In order to make sure that the parent class's __init__() code is executed as well, you need to call that parent class's __init__().

There are several ways of doing this:

#explicitly calling the __init__() of a specific class
#"list"--in this case
list.__init__(self, *args, **kwargs)     

#a little more flexible. If you change the parent class, this doesn't need to change
super(foo, self).__init__(*args, **kwargs) 

For more on super() see this question, for guidance on the pitfalls of super, see this article.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.