Python version: "'2.7.3 (default, Apr 10 2013, 06:20:15) \n[GCC 4.6.3]'"
I have this:
>>> 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>
Some more fun! Compare with results of testclass1 above.
>>> 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>
My question is how does (not why does) object__new__
behave differently in these two cases?
Also notice the error is kind of misleading in the first case because in the second case object.__new__
does end up taking an argument!.
Both object.__new__
and object.__init__
go through a carefully constructed maze of conditions that allow excess arguments in some cases, raise an error in others, and raise a warning in a very specific one. The code that implements the checks is easy enough to follow, but the reasoning behind it would likely remain inscrutable without this elucidating comment:
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.
The class that you are creating has its member __init__()
is called by new()
to handle any creation parameters but in the fist case you have no __init__
so can not pass any parameters.
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