gpt4 book ai didi

python - 为什么 object.__new__ 在这三种情况下的工作方式不同

转载 作者:太空狗 更新时间:2023-10-29 22:06:50 24 4
gpt4 key购买 nike

来自问题Why does or rather how does object.__new__ work differently in these two cases

作者感兴趣的不是为什么,而是如何。

我非常想知道为什么,特别是:

  1. 为什么 object.__init__ 没有打印参数而不是 object.__new__(在 testclass1 中)

  2. 为什么没有为 testclass3 引发错误? (因为它除了 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>

最佳答案

您使用的是较旧的 Python 版本;错误消息已更新:

>>> object.__new__(testclass1, 56)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object() takes no parameters

如果 __new____init__ 都没有被覆盖,Python 只会提示 __init__ 不支持参数;例如当您从 object 继承两者时。 testclass1 适合这种情况,testclass3 不适合,因为它有一个 __init__ 方法。

这是为了支持实现不使用 __init__ 的不可变类型(在这种情况下会从 object 继承), 可变类型,其中 __new__ 不应该关心 __init__ 期望的参数(通常是 更多 个参数)。

参见 issue 1683368 Guido van Rossum 解释了他这样做的动机。

typeobject.c source code有这样的话:

You may wonder why object.__new__() only complains about arguments
when object.__init__() is not overridden, and vice versa.

Consider the use cases:

  1. When neither is overridden, we want to hear complaints about excess (i.e., any) arguments, since their presence could indicate there's a bug.

  2. 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.

  3. 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.

  4. When __init__() is overridden, and the subclass __init__() calls object.__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.

请注意,.__init__() 方法自身 仍会报错!当你创建一个实例时,__new____init__ 都会被调用;您的代码仅直接调用 __new__调用 __init__!如果传入参数,创建 testclass1testclass3 的实例都会失败:

>>> 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__ 的特定错误.

关于python - 为什么 object.__new__ 在这三种情况下的工作方式不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19277399/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com