【问题标题】:Why does object.__new__ with arguments work fine in Python 2.x and not in Python 3.3+?为什么带有参数的 object.__new__ 在 Python 2.x 中可以正常工作,而在 Python 3.3+ 中却不行?
【发布时间】:2014-07-01 14:34:17
【问题描述】:

为什么以下代码在 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

【问题讨论】:

标签: python python-3.3 python-2.x


【解决方案1】:

object.__new__ 总是忽略额外的参数,并且至少从 Python 2.6 开始发出DeprecationWarning

您在 2.7 和 3.2 中看不到 DeprecationWarning 的原因是,从 2.7 和 3.2 开始,DeprecationWarning 一直是 suppressed by default;如果您使用python -WdPYTHONWARNINGS=default,您将看到警告。

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

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

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

由于TestB 派生自TestA,因此额外的参数will be passed to TestB.__init__

【讨论】:

    【解决方案2】:

    您可以像这样将 __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__ 的类的构造函数(__init__)(其中在这种情况下也是TestA)。

    【讨论】:

      猜你喜欢
      • 2016-08-26
      • 1970-01-01
      • 2017-03-12
      • 1970-01-01
      • 2014-03-01
      • 1970-01-01
      • 2021-10-04
      • 2019-11-27
      • 2020-10-03
      相关资源
      最近更新 更多