Python NotImplemented常量

Python NotImplemented constant

decimal.py来看,它在许多特殊的方法中使用NotImplemented。例如

1
2
3
4
5
6
class A(object):
    def __lt__(self, a):
        return NotImplemented

    def __add__(self, a):
        return NotImplemented

python文档说:

NotImplemented

Special value which can be returned by the"rich comparison"
special methods (__eq__(), __lt__(),
and friends), to indicate that the
comparison is not implemented with
respect to the other type.

它不讨论其他特殊的方法,也不描述行为。

它似乎是一个神奇的对象,如果从其他特殊方法返回,则会引发TypeError,而在"丰富的比较"中,特殊方法则毫无用处。

例如

1
print A() < A()

打印True,但

1
print A() + 1

提出TypeError,所以我很好奇发生了什么,未实现的用法/行为是什么。


NotImplemented允许您指示尚未实现两个给定操作数之间的比较(而不是指示比较有效,而是为两个操作数生成False)。

从python语言参考:

For objects x and y, first x.__op__(y)
is tried. If this is not implemented
or returns NotImplemented,
y.__rop__(x) is tried. If this is also
not implemented or returns
NotImplemented, a TypeError exception
is raised. But see the following
exception:

Exception to the previous
item: if the left operand is an
instance of a built-in type or a
new-style class, and the right operand
is an instance of a proper subclass of
that type or class and overrides the
base's __rop__() method, the right
operand's __rop__() method is tried
before the left operand's __op__()
method. This is done so that a
subclass can completely override
binary operators. Otherwise, the left
operand's __op__() method would always
accept the right operand: when an
instance of a given class is expected,
an instance of a subclass of that
class is always acceptable.


实际上,从__add__返回与从__lt__返回具有相同的含义,区别在于python 2.x在放弃之前尝试其他方式比较对象。python 3.x确实会引发类型错误。实际上,python也可以为__add__尝试其他东西,比如看__radd__和(尽管我对此很模糊)__coerce__

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 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文档)。


如果您从__add__返回它,它将表现为对象没有__add__方法,并引发TypeError

如果从一个丰富的比较函数返回NotImplemented,python的行为将类似于该方法没有实现,也就是说,它将推迟使用__cmp__