Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__new__ function behaves differently after overriding it with setattr

I have the following:

class A:
    def __init__(self, x):
        self.x = x

A(5)  # Works fine
x = A.__new__  # Save the function
A.__new__ = lambda y: y  # Temporarily override it
A.__new__ = x  # Restore the function
A(5)  # RAISES AN EXCEPTION!

The last call raises an exception:

TypeError: object.__new__() takes exactly one argument (the type to instantiate)

What happens here?

I'll add that x, prior to the override, was being called just fine as a __new__ function. But after the override (and the restore), it lost its ability to accept any number of arguments (*args, **kwargs).

like image 921
user9185231 Avatar asked Oct 24 '25 03:10

user9185231


1 Answers

This is happening because of the way Python handles __new__ .
When you do:
x = A.__new__,

x is actually a bound function.

When you assign the __new__ function back:

A.__new__ = x

the bound method is getting assigned to A.__new__. But __new__ is actually a static method, which also expects the class as its first argument.

To solve this, you can save an unbound version of __new__ back instead of the bound one.

class A:
    def __init__(self, x):
        self.x = x


def original_new(cls, *args, **kwargs):
    return object.__new__(cls)


A.__new__ = lambda y: y

A.__new__ = staticmethod(original_new)

a = A(5)
print(a.x) # 5

This is a complicated topic, so feel free to ask any questions!

like image 98
Aadvik Avatar answered Oct 27 '25 04:10

Aadvik