Python版:“'2.7.3(默认,2013年4月10日,06:20:15)\ n [GCC 4.6.3]'”
我有这个:
>>> 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>
更有趣!与上面的testclass1的结果进行比较。
>>> 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>
我的问题是 (不是为什么)object__new__
在这两种情况下表现不同?
另请注意,在第一种情况下,错误有点误导,因为在第二种情况下,object.__new__
最终会引发争论!。
答案 0 :(得分:5)
object.__new__
和object.__init__
都经过精心构造的迷宫条件,在某些情况下允许过多的论据,在其他情况下引发错误,并在非常具体的情况下发出警告。 The code that implements the checks很容易遵循,但如果没有this elucidating comment,其背后的推理可能仍然难以理解:
你可能想知道为什么
object.__new__()
只抱怨争论 当object.__init__()
未被覆盖时,反之亦然。考虑用例:
当两者都没有被覆盖时,我们希望听到关于过多(即任何)论点的投诉,因为他们的存在可能表明存在 错误。
定义不可变类型时,我们可能只覆盖
__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中,我们将警告关于多余的参数 方法被覆盖;对于所有其他情况,我们将使用上述规则。
答案 1 :(得分:3)
您正在创建的类的成员__init__()
由new()
调用以处理任何创建参数,但在第一种情况下,您没有__init__
所以无法传递任何参数。
答案 2 :(得分:3)
__new__
静态方法将类作为其第一个参数。其他参数将传递给该类的__init__
方法。由于您的班级没有__init__
方法,__new__
将不接受其他参数。
请查看the documentation了解详情。
至于“how”,它是用C(Objects/typeobject.c
)实现的,但你可以用纯Python执行相同的检查:
def __new__(cls, *args, **kwargs):
...
if not hasattr(cls, '__init__') and (args or kwargs):
raise TypeError("object.__init__() takes no parameters")
...