gpt4 book ai didi

python - 确定 super().__new__ 在 Python 3 中是否为 object.__new__?

转载 作者:太空狗 更新时间:2023-10-29 18:04:43 24 4
gpt4 key购买 nike

假设我有一些调用 __new__ 的类,我如何才能很好地使用 mro 并根据需要调用父类(super class)的 __new__(带参数),但不使用附加参数调用 object.__new__?例如。这仅在您不向构造函数传递任何参数时才有效:

class A(object):
def __new__(cls, *args, **kwargs):
print("A.__new__ called")
return super(A, cls).__new__(cls, *args, **kwargs)

class B(object):
def __new__(cls, *args, **kwargs):
print("B.__new__ called")
return super(B, cls).__new__(cls, *args, **kwargs)

class C(A, B): pass

>>> C.mro()
[__main__.C, __main__.A, __main__.B, builtins.object]
>>> C()
A.__new__ called
B.__new__ called

但是带参数调用会导致它失败(因为在某些时候 Python 更改为 object.__new__ 除了调用者类之外不接受任何参数):

>>> C(1)
A.__new__ called
B.__new__ called
Traceback (most recent call last):
...
TypeError: object() takes no parameters

那么 AB 怎么知道它们的父类(super class)是 object 呢?我应该做类似 super(A, cls).__new__ is object.__new__ 的事情吗?检查 mro()[1] == builtins.object?还是我只需要决定“A 将 永远不会 尝试在 __new__ 中很好地调用父类(super class)”(例如通过执行 return object.__new__(cls))?

编辑:如果该类定义了一个自定义的 __init__ 方法,Python 2.6 和 Python 2.7 可以使用它,但它仍然不能在 Python 3 中工作。

最佳答案

如果我们看一下 CPython source ,我们看到:

  • object.__new__ 如果使用额外的参数调用将出错,__new__ 被覆盖或者 __init__ 不是 覆盖;同样,
  • object.__init__ 如果使用额外的参数调用将出错,__init__ 被覆盖或 __new__ 不是 覆盖

在 2.x 中,错误只是一个 DeprecationWarning,您可能在试验时错过了(请注意,自 2.7 和 3.2 以来,DeprecationWarningsuppressed by default) .

这种行为的理由是类型要么是不可变的 - 在这种情况下它们应该在 __new__ 中使用参数 - 或者是可变的 - 在这种情况下它们应该在 __init__ 中使用参数>。这似乎是实用性胜过纯粹性的案例;很难想到 __new__ 委托(delegate)给父类(super class)型(而不是仅仅记录/跟踪)的许多生产性用途,并且 会更常见 super 调用带有额外参数的 object.__new__ 是错误的。

处理这个问题的最干净的方法是检查身份:super(A, cls).__new__ is object.__new__。理由:

  • 这是 CPython 决定是否出错的方式(在 C 中而不是 Python 中,但逻辑是相同的):

    if (excess_args(args, kwds) &&
    (type->tp_init == object_init || type->tp_new != object_new)) {
    PyErr_SetString(PyExc_TypeError, "object() takes no parameters");
    return NULL;
    }
  • object.__new__ 不对参数做任何事情,除了决定是否出错。

关于python - 确定 super().__new__ 在 Python 3 中是否为 object.__new__?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19718062/

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