作者对原因不感兴趣,而是对如何感兴趣。
我非常想了解原因,特别是:
为什么object.__init__
没有打印参数而不是object.__new__ (in testclass1)
为什么没有为testclass3引发错误? (因为除了自我之外不需要任何参数)
码
>>> 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>
答案 0 :(得分:15)
您使用的是较旧的Python版本;此后错误消息已更新:
>>> object.__new__(testclass1, 56)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object() takes no parameters
如果__init__
和__new__
都没有被覆盖,Python只会抱怨__init__
不支持参数;例如当你从object
继承时。 testclass1
符合这种情况,testclass3
没有,因为它有__init__
方法。
这是为了支持实现不能用于__init__
的不可变类型(在这种情况下将从object
继承),和可变类型,其中__new__
不应该关注__init__
期望的参数(通常是 more 参数)。
见issue 1683368 Guido van Rossum解释他的动机。
你可能想知道为什么
object.__new__()
只抱怨论据 当object.__init__()
未被覆盖时,反之亦然。考虑用例:
当两者都没有被覆盖时,我们希望听到有关的投诉 超出(即任何)论据,因为他们的存在可以 表明存在错误。
定义Immutable类型时,我们可能只会覆盖
__new__()
,因为调用__init__()
太晚无法初始化 不可改变的对象。由于__new__()
定义了签名 类型,必须覆盖__init__()
只是为了痛苦 阻止它抱怨过多的争论。定义Mutable类型时,我们可能只覆盖
__init__()
。所以这里反过来的推理适用:我们没有 想要覆盖__new__()
只是为了阻止它 侵犯。- 醇>
覆盖
__init__()
时,子类__init__()
会调用object.__init__()
,后者应该抱怨过剩 参数;同上__new__()
。用例2和3使得无条件检查没有吸引力 多余的论点。解决所有四种用途的最佳解决方案 案例如下:
__init__()
抱怨过多的论点 除非__new__()
被覆盖且__init__()
未被覆盖 (IOW,如果覆盖__init__()
或未覆盖__new__()
); 对称地,__new__()
抱怨过多的论点,除非 覆盖__init__()
并且不会覆盖__new__()
(IOW,如果覆盖__new__()
或未覆盖__init__()
)。但是,为了向后兼容,这会破坏太多代码。 因此,在2.6中,我们将警告关于多余的参数 方法被覆盖;对于所有其他情况,我们将使用上述内容 规则。
请注意,.__init__()
方法本身仍会抱怨!创建实例时,会调用__new__
和__init__
;您的代码只会直接调用__new__
并且不调用__init__
!如果传入参数,则创建testclass1
和testclass3
的实例都会失败:
>>> 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)
唯一的区别是,对于testclass1
,object()
的默认方法是投诉自定义__init__
的特定错误。