编码异常类,我遇到了这个错误:
TypeError: object.__new__(A) is not safe, use Exception.__new__()
这里有一个类似的问题:
TypeError:object .__ new __(int)不安全,使用int .__ new __().所以__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引发错误的条件是什么?
打电话没有问题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)