为什么带有参数的object .__ new__在Python 2.x中运行良好,而在Python 3.3+中运行不正常?

tbi*_*icr 8 python python-2.x python-3.3

为什么以下代码在Python 2.x中运行良好,而在Python 3.3+中运行不正常:

class TestA(object):
    def __new__(cls, e):
        return super(TestA, cls).__new__(TestB, e)

class TestB(TestA):
    def __init__(self, e):
        print(self, e)

TestA(1)
Run Code Online (Sandbox Code Playgroud)

Python 2.7.6输出:

(<__main__.TestB object at 0x7f6303378ad0>, 1)
Run Code Online (Sandbox Code Playgroud)

Python 3.1.5输出:

__main__:3: DeprecationWarning: object.__new__() takes no parameters
<__main__.TestB object at 0x7f2f69db8f10> 1
Run Code Online (Sandbox Code Playgroud)

Python 3.2.3和3.2.5输出:

<__main__.TestB object at 0xcda690> 1
Run Code Online (Sandbox Code Playgroud)

Python 3.3.5和3.4.1输出:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __new__
TypeError: object() takes no parameters
Run Code Online (Sandbox Code Playgroud)

eca*_*mur 6

object.__new__一直忽略额外的参数,并且DeprecationWarning至少从 Python 2.6 开始发布。

DeprecationWarning在 2.7 和 3.2中没有看到的原因是因为 2.7 和 3.2DeprecationWarning已被默认抑制;如果你使用python -WdorPYTHONWARNINGS=default那么你会看到警告。

在 Python 3.3 中DeprecationWarning被转换为错误。

编写代码的正确方法(在任何版本的 Python 中)是吞下额外的参数TestA.__new__

class TestA(object):
    def __new__(cls, e):
        return super(TestA, cls).__new__(TestB)
Run Code Online (Sandbox Code Playgroud)

由于TestB是从 派生的TestA,额外的参数将被传递给TestB.__init__