在__new__中使用object .__ new__的缺点是什么?

dir*_*obs 6 python

编码异常类,我遇到了这个错误:

TypeError: object.__new__(A) is not safe, use Exception.__new__()

这里有一个类似的问题: TypeError:object .__ new __(int)不安全,使用int .__ new __().所以__new__因以下原因而被弃用:

[Python-Dev] __new__弃用

Guido van Rossum

"这条消息意味着它所说的内容.:-)调用object.__new__()多个类参数是没有意义的 ,任何这样做的代码都只是将这些args转移到一个黑洞中."

但我在3.3中发出的"不安全"的警告是可怕的.我试着理解使用的含义object.__new__,让我们考虑一下这个例子:

>>> class A(Exception):
...     def __new__(cls, *args):
...             return object.__new__(A)
...
>>> A()
TypeError: object.__new__(A) is not safe, use Exception.__new__()
Run Code Online (Sandbox Code Playgroud)

悲惨地失败.另一个例子:

>>> class A(object):
...     def __new__(cls, *args):
...             return object.__new__(A)
...
>>>
>>> A()
<__main__.A object at 0x0000000002F2E278>
Run Code Online (Sandbox Code Playgroud)

工作良好.虽然,object就像Exception他们的角色一样,它是一个内置类,但它们共享内置类的特性.现在Exception,第一个例子提出TypeError,但是object,它没有?

(a)在第一个示例中,使用object.__new__Python来提高error(TypeError:...is not safe...)的缺点是什么?

(b)在调用之前Python执行什么样的检查__new__?或者:在第一个示例中,Python引发错误的条件是什么?

zvo*_*one 5

打电话没有问题object.__new__,但不打电话就有问题Exception.__new__。

Exceptionclass 的设计方式是__new__必须调用它是至关重要的,因此如果没有调用它,它就会抱怨。

有一个问题,为什么只有内置类才会发生这种情况。实际上,Python 对每个被编程为这样做的类都这样做了。

这是自定义类中相同机制的简化穷人实现:

class A(object):
    def __new__(cls):
        rtn = object.__new__(cls)
        rtn.new_called = True
        return rtn

    def __init__(self):
        assert getattr(self,'new_called',False), \
            "object.__new__ is unsafe, use A.__new__"

class B(A):
    def __new__(cls):
        return object.__new__(cls)
Run Code Online (Sandbox Code Playgroud)

现在:

>>> A()
<__main__.A object at 0x00000000025CFF98>

>>> B()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in __init__
AssertionError: object.__new__ is unsafe, use A.__new__
Run Code Online (Sandbox Code Playgroud)

作为旁注,问题中的这个例子实际上有两个错误:

>>> class A(Exception):
...     def __new__(cls, *args):
...             return object.__new__(A)
Run Code Online (Sandbox Code Playgroud)

第一个是__new__被调用object,从而忽略Exception.__new__。

另一个,同样严重的A是传递给__new__而不是cls,这阻碍了从 继承的所有类A。

看这个例子:

class A(object):
    def __new__(cls):
        return object.__new__(A)  # The same erroneous line, without Exception

class B(A):
    pass
Run Code Online (Sandbox Code Playgroud)

现在B()不创建一个实例B:

>>> B()
<__main__.A object at 0x00000000025D30B8>
Run Code Online (Sandbox Code Playgroud)