Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't __new__ in Python new-style classes a class method?

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 the classmethod 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"?

like image 274
Dolda2000 Avatar asked Feb 01 '12 07:02

Dolda2000


People also ask

Is __ new __ a class method?

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.

What is __ new __ method in Python?

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.

What is new style class in Python?

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.

When a new instance of a class is created which method gets?

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.


1 Answers

__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 with object.__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()) 
like image 161
jfs Avatar answered Oct 19 '22 08:10

jfs