the author wasn’t interested in the why, but rather in the how.
I would very much want to understand why, particularly :
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)
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
__init__ have been overridden; e.g. when you inherit both from
testclass1 fits that case,
testclass3 does not because it has an
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.
typeobject.c source code has this to say:
You may wonder why
object.__new__()only complains about arguments
object.__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
__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
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
__init__()is overridden, and the subclass
object.__init__(), the latter should complain about excess
arguments; ditto for
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
__new__()is overridden and
__init__()is not overridden
__init__()is overridden or
__new__()is not overridden);
__new__()complains about excess arguments unless
__init__()is overridden and
__new__()is not overridden
__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
Note that the
.__init__() method itself will still complain! When you create an instance, both
__init__ are called; your code only calls
__new__ directly and does not invoke
__init__! Creating an instance of
testclass3 both fails if you pass in arguments:
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)testclass1(
The only difference is that for
testclass1 it is the default methods for
object() that complain instead a specific error for the custom