Python中的NotImplemented常量
在查看 decimal.py
文件时,发现它在很多特殊方法中使用了 NotImplemented
。比如:
class A(object):
def __lt__(self, a):
return NotImplemented
def __add__(self, a):
return NotImplemented
根据Python文档的说法:
NotImplemented
这是一个特殊的值,可以由“丰富比较”特殊方法(比如
__eq__()
、__lt__()
等)返回,用来表示与其他类型的比较没有实现。
文档没有提到其他特殊方法,也没有描述它的具体行为。
看起来这个 NotImplemented
是一个神奇的对象,如果从其他特殊方法返回它,会引发 TypeError
错误,而在“丰富比较”特殊方法中则不会有任何效果。
例如:
print A() < A()
这段代码会打印出 True
,但是
print A() + 1
这段代码会引发 TypeError
错误,所以我很好奇 NotImplemented
到底是怎么回事,它的用法和行为是什么。
3 个回答
如果你在__add__
这个方法里返回一个值,Python会觉得这个对象根本没有__add__
这个方法,然后就会报一个TypeError
的错误。
如果你在一个比较函数里返回NotImplemented
,Python会认为这个方法没有被实现,也就是说它会去使用__cmp__
这个方法来处理。
其实从 __add__
和 __lt__
返回的结果是一样的,主要的区别在于 Python 2.x 会尝试其他方法来比较对象,如果这些方法都不行才会放弃。而在 Python 3.x 中,如果比较失败,就会直接抛出一个类型错误(TypeError)。实际上,Python 在处理 __add__
时也可以尝试其他方法,比如 __radd__
和(虽然我不太确定) __coerce__
。
# 2.6
>>> class A(object):
... def __lt__(self, other):
... return NotImplemented
>>> A() < A()
True
# 3.1
>>> class A(object):
... def __lt__(self, other):
... return NotImplemented
>>> A() < A()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: A() < A()
想了解更多信息,可以查看 关于排序比较的文档(3.0 版本)。
NotImplemented
是一个用来表示两个给定的操作数之间的比较没有被实现的标记。这并不是说比较是有效的,但结果是 False
。
根据 Python语言参考:
对于对象 x 和 y,首先会尝试
x.__op__(y)
。如果这个方法没有被实现或者返回NotImplemented
,那么接下来会尝试y.__rop__(x)
。如果这个方法也没有被实现或者返回NotImplemented
,就会抛出一个类型错误(TypeError)。不过,下面有一个例外:
对于上面提到的情况的例外是:如果左边的操作数是一个内置类型的实例或者是一个新式类的实例,而右边的操作数是这个类型或类的一个合适的子类的实例,并且重写了基类的
__rop__()
方法,那么会先尝试右边操作数的__rop__()
方法,而不是左边操作数的__op__()
方法。这样做是为了让子类可以完全重写二元操作符。否则,左边操作数的__op__()
方法总是会接受右边的操作数:当期望一个特定类的实例时,任何该类的子类的实例都是可以接受的。