[issue21415] Python __new__ method doc typo (it's a class and not a static method)
New submission from Jurko Gospodnetić:
Doc/reference/datamodel.rst documentation states that
the __new__ method is a static method (in Python, not
in C!) when it is in fact a class method.
A patch has been prepared in the
https://bitbucket.org/jurko/cpython repository.
branch: datamodel_doc_typo_fix
commit: 81c5ba188805e42292c3eb9cffa56fbd5b7c6aee
But it'll probably be easier for you to just change
that single word directly. :-D
Hope this helps.
Best regards,
Jurko Gospodnetić
----------
assignee: docs@python
components: Documentation
hgrepos: 245
messages: 217748
nosy: Jurko.Gospodnetić, docs@python
priority: normal
severity: normal
status: open
title: Python __new__ method doc typo (it's a class and not a static method)
type: enhancement
versions: Python 3.5
_______________________________________
Python tracker
Changes by Jurko Gospodnetić
Steven D'Aprano added the comment:
Actually, no, it is a staticmethod. See Guido's tutorial from way back in version 2.2:
[quote]
__new__ is a static method. When defining it, you don't need to (but may!) use the phrase "__new__ = staticmethod(__new__)", because this is implied by its name (it is special-cased by the class constructor).
[end quote]
https://www.python.org/download/releases/2.2.3/descrintro
I believe that this explains why you have to use this idiom inside __new__ when using super():
def __new__(cls, x):
super().__new__(cls, x)
If __new__ were a classmethod, the first argument "cls" would be provided automatically.
If you try making __new__ a classmethod, it breaks:
py> class Test:
... @classmethod
... def __new__(cls):
... pass
...
py> x = Test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __new__() takes 1 positional argument but 2 were given
whereas a staticmethod works fine.
----------
nosy: +steven.daprano
resolution: -> not a bug
status: open -> closed
_______________________________________
Python tracker
eryksun added the comment:
I believe that this explains why you have to use this idiom inside __new__ when using super():
def __new__(cls, x): super().__new__(cls, x)
Yes, if __new__ is defined and is a function, type_new replaces it with a staticmethod:
http://hg.python.org/cpython/file/04f714765c13/Objects/typeobject.c#l2437
For example:
>>> class A: __new__ = lambda c: 0
>>> type(vars(A)['__new__'])
Jurko Gospodnetić added the comment: Thanks for the detailed response! :-( I should have tested more before reporting the issue. Sorry for the noise. :-( I saw the 'cls' argument and assumed it was a class method. Having to explicitly specify cls did not seem to be in contradiction with this since I assumed __new__ is generally invoked on the class directly. I still do not see why it had to be a static method and has not been implemented as a class method, but I guess I'll better ask that kind of a question on the python user's newsgroup. :-) Just in case it can help someone else, here's some sample code what convinced me __new__ was indeed implemented as a static method:
class X: pass X.__new__() # TypeError: object.__new__(): not enough arguments X.__new__(X) # creates a new X instance x = X() x.__new__() # TypeError: object.__new__(): not enough arguments x.__new__(X) # creates a new X instance
If __new__ had been a class method then calling
'x.__new__()' would have worked as well.
Thanks again for the replies!
Best regards,
Jurko Gospodnetić
----------
_______________________________________
Python tracker
Changes by Jesús Cea Avión
Eric Snow added the comment:
FYI, __new__() is a staticmethod to accommodate subclassing. Several things that happen at instantiation-time (when __new__() is called), including memory allocation, are tied to the class that is passed in and may be different for subclasses. For example:
class Spam(int):
def __new__(cls, value):
self = super().__new__(Spam, value)
self._eggs = 10
return self
Spam is passed in instead of int (as would happen if it were a classmethod), resulting in extra memory being allocated for _eggs (and for __dict__ among other things).
----------
nosy: +eric.snow
_______________________________________
Python tracker
participants (5)
-
Eric Snow
-
eryksun
-
Jesús Cea Avión
-
Jurko Gospodnetić
-
Steven D'Aprano