为什么Python 2.x中带参数的object.__new__正常工作而Python 3.3+中不行?

11 投票
2 回答
6546 浏览
提问于 2025-04-18 11:44

为什么下面的代码在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)

Python 2.7.6的输出结果:

(<__main__.TestB object at 0x7f6303378ad0>, 1)

Python 3.1.5的输出结果:

__main__:3: DeprecationWarning: object.__new__() takes no parameters
<__main__.TestB object at 0x7f2f69db8f10> 1

Python 3.2.3和3.2.5的输出结果:

<__main__.TestB object at 0xcda690> 1

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

2 个回答

1

你可以像下面这样把 __init__ 函数移动到 TestA:

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

    def __init__(self, e):
        print(self, e)

TestA(1)

注意,TestB 这个类不再需要了。

注意,在调用 object.__new__ 时,'e' 这个参数被省略了。object 类的 new 函数只需要一个类作为参数,而在重写的 __new__ 函数中(这里是 TestA 的),任何额外的参数会自动传递给传给 object.__new__ 的类的构造函数(在这个例子中也是 TestA 的构造函数 __init__)。

9

object.__new__ 一直以来都不会处理多余的参数,并且从 Python 2.6 开始就会发出一个 DeprecationWarning(弃用警告)。

你在 2.7 和 3.2 版本中没有看到这个 DeprecationWarning 的原因是,从这两个版本开始,DeprecationWarning 默认是被隐藏的;如果你使用 python -Wd 或者设置 PYTHONWARNINGS=default,那么你就能看到这个警告了。

在 Python 3.3 中,DeprecationWarning 被转变成了一个错误。

在任何版本的 Python 中,正确的写法是让 TestA.__new__ 忽略多余的参数:

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

因为 TestB 是从 TestA 继承而来的,所以多余的参数会被传递给 TestB.__init__

撰写回答