David Zheng
David Zheng

Reputation: 839

Why do we need to use __new__() when extending a immutable class in Python?

I am reading the book Mastering Object-Oriented Python. In the part of book where it talks about the __new__ method and immutable objects, it says something like the __new__() method is used to extend the immutable classes where the __init__() method can't easily be overridden. It also gives an example as below

class Float_Fail(float):
    def __init__(self, value, unit):
        super().__init__(value)
        self.unit = unit

f = Float_Fail(6.5, "knots")

TypeError Traceback (most recent call last)
<ipython-input-2-9511e6ca03be> in <module>()
----> 1 f = Float_Fail(6.5, "knots")
TypeError: float() takes at most 1 argument (2 given)

I'm just curious why float gives this error. I mean, we can initialize a float like this:

f = float(1.1)

Doesn't it mean the __init__() method of float class takes the number as it's second argument. If not, how is the initialization of an immutable class implemented in Python?

Upvotes: 1

Views: 978

Answers (2)

BrenBarn
BrenBarn

Reputation: 251548

If you do MyClass(1), then 1 is indeed passed as an argument to __init__. But __new__ is called before __init__, so 1 is first passed as an argument to __new__. The error you are seeing is because you didn't override __new__, so the inherited float.__new__ is being called, and it doesn't accept your extra argument. It never gets a chance to even try calling __init__, because it fails when trying to call __new__.

This is explained in the documentation. As clearly stated there, the arguments you pass when instiating a class (e.g., the 1 in MyClass(1)) are passed to both __new__ and __init__, in that order.

Upvotes: 3

kindall
kindall

Reputation: 184345

By the time the __init__ method runs, the object already exists. Since the object is immutable, its value can't be changed in __init__.

Upvotes: 0

Related Questions