Python中的NotImplemented常量

37 投票
3 回答
20168 浏览
提问于 2025-04-15 12:35

在查看 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 个回答

1

如果你在__add__这个方法里返回一个值,Python会觉得这个对象根本没有__add__这个方法,然后就会报一个TypeError的错误。

如果你在一个比较函数里返回NotImplemented,Python会认为这个方法没有被实现,也就是说它会去使用__cmp__这个方法来处理。

7

其实从 __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 版本)

37

NotImplemented 是一个用来表示两个给定的操作数之间的比较没有被实现的标记。这并不是说比较是有效的,但结果是 False

根据 Python语言参考

对于对象 x 和 y,首先会尝试 x.__op__(y)。如果这个方法没有被实现或者返回 NotImplemented,那么接下来会尝试 y.__rop__(x)。如果这个方法也没有被实现或者返回 NotImplemented,就会抛出一个类型错误(TypeError)。不过,下面有一个例外:

对于上面提到的情况的例外是:如果左边的操作数是一个内置类型的实例或者是一个新式类的实例,而右边的操作数是这个类型或类的一个合适的子类的实例,并且重写了基类的 __rop__() 方法,那么会先尝试右边操作数的 __rop__() 方法,而不是左边操作数的 __op__() 方法。这样做是为了让子类可以完全重写二元操作符。否则,左边操作数的 __op__() 方法总是会接受右边的操作数:当期望一个特定类的实例时,任何该类的子类的实例都是可以接受的。

撰写回答