nextdoordoc
nextdoordoc

Reputation: 1767

Why inserting __init__() of superclass in this case?

I am now reading HeadFirstPython and there is an example about class.

>>> class NamedList(list):
>>>    def __init__(self, a_name):
>>>        list.__init__([])
>>>        self.name = a_name

In this case why is the statement list.__init__([]) used? And also cannot understand why it is including the empty [].

Upvotes: 1

Views: 105

Answers (2)

Lauritz V. Thaulow
Lauritz V. Thaulow

Reputation: 51015

The code from the book contains an error. The line list.__init__([]) is missing an argument, and commenting it out makes no difference whatsoever, except speeding up your program slightly.

I almost couldn't believe it when I read your question, because I recently answered a similar question about code from another book ("Learning Python") that contains exactly the same error.

Here's the corrected line:

        list.__init__(self, [])

When calling methods (that are not static methods or class methods) directly on class objects, the normally implicit first argument self must be provided explicitly. Another way to correct the line would be by using super, which makes the self argument implicit.

        super(NamedList, self).__init__([])

The [] argument is unnecessary in either case, but it's a good habit to write explicit code, and in this case it communicates that we really want the list to be empty.

What the code in the book does is to provide an empty list ([]) as the self argument. This causes that list to be initialized (over again), after which it is soon garbage collected since no reference to it is kept anywhere. In other words, the whole line is dead code.

To verify that the original line has no effect is easy: temporarily change [] in list.__init__([]) to a non-empty list and observe that the resulting NamedList instance doesn't contain those elements. Then insert self as the first argument, and observe that the items in the list are now added to the NamedList instance.

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1124070

Normally, because it is good practice to call the initializer of the class you are inheriting from.

However, the author seems to have substituted self for an empty list; I'd have used one of:

super(NamedList, self).__init__()
super(NamedList, self).__init__([])

or at the very least provided an explicit self argument:

list.__init__(self)

In this case, you are subclassing list; it's initializer takes a initial list of elements to start with, but your own initializer only takes a_name, so the superclass initializer is passed an explicit empty list.

The list.__init__() method does little more than clear and extend; it is the equivalent of self.clear(); self.extend(argument), resetting it's size and making it re-usable in case __init__() is called multiple times.

Passing in a new list object to the list initializer makes the call entirely useless and a no-op; that's an error that must've slipped by the technical review.

Upvotes: 2

Related Questions