The Changelog for Python 2.2 (where new-style classes were introduced) says the following about the __new__
function:
__new__
is a static method, not a class method. I initially thought it would have to be a class method, and that's why I added theclassmethod
primitive. Unfortunately, with class methods, upcalls don't work right in this case, so I had to make it a static method with an explicit class as its first argument.
However, I cannot think of why class methods wouldn't work for this purpose, and it would certainly look better. Why didn't __new__
end up as a class method in the end? What does Guido refer to when he says that "upcalls don't work right in this case"?
The __new__() is a static method of the object class. When you create a new object by calling the class, Python calls the __new__() method to create the object first and then calls the __init__() method to initialize the object's attributes.
In the base class object , the __new__ method is defined as a static method which requires to pass a parameter cls . cls represents the class that is needed to be instantiated, and the compiler automatically provides this parameter at the time of instantiation.
New-style classes were introduced in Python 2.2 to unify the concepts of class and type. A new-style class is simply a user-defined type, no more, no less. If x is an instance of a new-style class, then type(x) is typically the same as x.
Constructors in Python Of one particular interest is the __init__() function. This special function gets called whenever a new object of that class is instantiated. This type of function is also called constructors in Object Oriented Programming (OOP). We normally use it to initialize all the variables.
__new__
being static method allows a use-case when you create an instance of a subclass in it:
return super(<currentclass>, cls).__new__(subcls, *args, **kwargs)
If new
is a class method then the above is written as:
return super(<currentclass>, cls).new(*args, **kwargs)
and there is no place to put subcls
.
I don't really see when that would be a proper use of
__new__
, though. Maybe I'm not seeing it, but that just seems to me to be a completely pathological use of it (and it should be said, that if you still really want it, then you could access it withobject.__new__.__func__
). At the very least, I find it very hard to imagine that it would have been the reason for Guido to change__new__
from being a class method to a static method.
A more common case would be to call parent __new__
without using super()
. You need a place to pass cls
explicitly in this case:
class Base(object): @classmethod def new(cls): print("Base.new(%r)" % (cls,)) return cls() class UseSuper(Base): @classmethod def new(cls): print("UseSuper.new(%r)" % (cls,)) return super(UseSuper, cls).new() # passes cls as the first arg class NoSuper(Base): @classmethod def new(cls): print("NoSuper.new(%r)" % (cls,)) return Base.new() # passes Base as the first arg class UseFunc(Base): @classmethod def new(cls): print("UseFunc.new(%r)" % (cls,)) return Base.new.im_func(cls) # or `.__func__(cls)`. # passes cls as the first arg print(UseSuper.new()) print('-'*60) print(NoSuper.new()) print('-'*60) print(UseFunc.new())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With