导读:本文讨论 Python 的 NotImplemented
它是什么,它意味着什么,什么时候应该使用。
是什么
>>> type(NotImplemented)
<type 'NotImplementedType'>
NotImplemented
是 Python 内置命名空间中的六个常量之一。其他还有 False
, True
, None
, Ellipsis
和 __debug__
。类似于 Ellipsis
,NotImplemented
可以重新赋值。 赋值给它,即使作为属性名称,也不会引发SyntaxError
异常,所以它不是真正的“真实(real/true)”的常量。当然,我们永远都不应该重新赋值它。
但是,为了完整:
>>> None = 'hello'
...
SyntaxError: can't assign to keyword
>>> NotImplemented
NotImplemented
>>> NotImplemented = 'do not'
>>> NotImplemented
'do not'
意味着什么,什么时候用
NotImplemented
是 python 特殊二元方法(例如__eq__()
, __lt__()
, __add__()
, __rsub__()
)返回的特殊值,表示该操作没有针对其他类型实现。而且,它转换成 bool 类型表示 true
:
>>> bool(NotImplemented)
True
可能会有这样的疑问「应该在操作没有实现时抛出NotImpementedError
异常」,通过一些例子,我们将看到为什么在实现二元特殊方法时不应该这样。
让我们通过为两个非常基本的(但无用的)类 A 和 B 编写一个 __eq__
来展示NotImplemented
常量的使用。[对于这个简单的例子,为避免分心不实现__ne__()
。但通常来说,除非有充分的理由,否则每次实现__eq__()
,也应该实现__ne__()
。]
# example.py
class A(object):
def __init__(self, value):
self.value = value
def __eq__(self, other):
if isinstance(other, A):
print('Comparing an A with an A')
return other.value == self.value
if isinstance(other, B):
print('Comparing an A with a B')
return other.value == self.value
print('Could not compare A with the other class')
return NotImplemented
class B(object):
def __init__(self, value):
self.value = value
def __eq__(self, other):
if isinstance(other, B):
print('Comparing a B with another B')
return other.value == self.value
print('Could not compare B with the other class')
return NotImplemented
现在在 interpreter 中:
>>> from example import A, B
>>> a1 = A(1)
>>> b1 = B(1)
现在我们可以尝试对__eq __()
的不同调用并查看会发生什么。提醒一下,在 Python 中,a == b
实际上是调用 a.__eq__(b)
:
>>> a1 == a1
Comparing an A with an A
True
如预期的那样,a1 等于 a1(本身),A 类中的__eq __() 方法处理此操作。将 b1 与自身进行比较也会得出类似的结果:
>>> b1 == b1
Comparing a B with another B
True
如果我们现在比较 a1 和 b1,会怎么样?由于 A 的__eq __()
会检查 other 参数是不是 B 的实例,我们期望 a1 .__ eq __(b1)
处理比较操作并返回 True:
>>> a1 == b1
Comparing an A with a B
True
现在,如果我们将 b1 与 a1 进行比较(即调用 b1.__eq__(a1)
),我们应该期望返回NotImplemented
。这是因为 B 的__eq __()
仅与其他 B 的实例进行比较。让我们看看发生了什么:
>>> b1 == a1
Could not compare B against the other class
Comparing an A with a B
True
b1 .__ eq __(a1)
方法返回 NotImplemented
导致 A 的__eq __()
方法被调用,并且由于在 A 的__eq __()
中定义了 A 和 B 之间的比较,我们得到了正确的结果(True)。
这就是返回 NotImplemented
所做的事情。NotImplemented
告诉运行时它应该请求 other 来满足操作。 在表达式b1 == a1
中,b1 .__ eq __(a1)
返回 NotImplemented
,它告诉 Python 尝试调用 a1 .__ eq __(b1)
。 由于 a1 足够知道返回 True,所以表达式可以成功。
如果 A 的__eq __()
也返回NotImplemented
,那么运行时将回退到基于对象标识(在 CPython 中是对象在内存中的地址)的相等内置行为。
注意,当b1 .__ eq __(a1)
失败时抛出一个NotImpementedError
异常会突破代码调用,除非被捕获,但 NotImplemented
不会被抛出并可以用于进一步的测试。
原文:Python’s `NotImplemented` Type
扩展阅读:
极光日报,极光开发者旗下媒体。
每天导读三篇英文技术文章。