from question Why does or rather how does object.__new__ work differently in these two cases
the author wasn't interested in the why, but rather in the how.
I would very much want to understand why, particularly :
why isn't object.__init__ takes no parameters printed instead of object.__new__ (in testclass1)
why no error is raised for testclass3 ? (as it takes no arguments other than self)
code
>>> class testclass1(object):
... pass
...
>>> class testclass2(object):
... def __init__(self,param):
... pass
...
>>> a = object.__new__(testclass1, 56)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object.__new__() takes no parameters
>>> b = object.__new__(testclass2, 56)
>>> b
<__main__.testclass2 object at 0x276a5d0>
>>> class testclass3(object):
... def __init__(self):
... pass
...
>>> c = object.__new__(testclass3, 56)
>>> c
<__main__.testclass3 object at 0x276a790>
>>> c1 = object.__new__(testclass3)
>>> c1
<__main__.testclass3 object at 0x276a810>
You are using an older Python version; the error message has since been updated:
>>> object.__new__(testclass1, 56)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object() takes no parameters
Python will only complain about __init__ not supporting arguments if neither __new__ nor __init__ have been overridden; e.g. when you inherit both from object. testclass1 fits that case, testclass3 does not because it has an __init__ method.
This is to support implementing immutable types that don't have a use for __init__ (which would be inherited from object in that case), and mutable types, where __new__ should not care about what arguments __init__ expects (which usually would be more arguments).
See issue 1683368 where Guido van Rossum explains his motivations for this.
The typeobject.c source code has this to say:
You may wonder why
object.__new__()only complains about arguments
whenobject.__init__()is not overridden, and vice versa.Consider the use cases:
When neither is overridden, we want to hear complaints about excess (i.e., any) arguments, since their presence could indicate there's a bug.
When defining an Immutable type, we are likely to override only
__new__(), since__init__()is called too late to initialize an Immutable object. Since__new__()defines the signature for the type, it would be a pain to have to override__init__()just to stop it from complaining about excess arguments.When defining a Mutable type, we are likely to override only
__init__(). So here the converse reasoning applies: we don't want to have to override__new__()just to stop it from complaining.When
__init__()is overridden, and the subclass__init__()callsobject.__init__(), the latter should complain about excess arguments; ditto for__new__().Use cases 2 and 3 make it unattractive to unconditionally check for excess arguments. The best solution that addresses all four use cases is as follows:
__init__()complains about excess arguments unless__new__()is overridden and__init__()is not overridden (IOW, if__init__()is overridden or__new__()is not overridden); symmetrically,__new__()complains about excess arguments unless__init__()is overridden and__new__()is not overridden (IOW, if__new__()is overridden or__init__()is not overridden).However, for backwards compatibility, this breaks too much code. Therefore, in 2.6, we'll warn about excess arguments when both methods are overridden; for all other cases we'll use the above rules.
Note that the .__init__() method itself will still complain! When you create an instance, both __new__ and __init__ are called; your code only calls __new__ directly and does not invoke __init__! Creating an instance of testclass1 and testclass3 both fails if you pass in arguments:
>>> testclass1(56)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object() takes no parameters
>>> testclass3(56)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() takes exactly 1 argument (2 given)
The only difference is that for testclass1 it is the default methods for object() that complain instead a specific error for the custom __init__.
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