前言
Python 中的 NotImplemented
和 NotImplementedError
很像,都用来表示没有实现的意思。它们具体有什么区别呢?
NotImplemented
NotImplemented 是 Python 中的一个特殊常量,注意它不是一个异常类,是一个值。所以它是用在 return 后面,而不是 raise。它是 types.NotImplementedType 类型的唯一实例。
它主要用于重载自定义二元方法中,如 __add__
, __eq__
,__lt__
等,这些方法用于定义类实例的相加(+)、相等(==)、小于(<)等比较操作。当方法返回 NotImplemented 时,表示这个操作是没有实现的。
class MyClass:
def __init__(self, value):
self.value = value
def __add__(self, other):
if isinstance(other, MyClass):
return MyClass(self.value + other.value)
elif isinstance(other, int):
return MyClass(self.value + other)
else:
return NotImplemented
def __str__(self):
return str(self.value)
a = MyClass(3)
b = 2
c = a + b # c 的值为 5,因为处理了 int 类型
d = a + "test" # 会报 TypeError,因为返回了 NotImplemented
NotImplementedError
NotImplementedError 是 Python 内置的异常类,通过 raise 抛出,用于表示一个方法或函数没有被实现。通常可以用于抽象基类的抽象方法中,让子类必须去覆盖方法。
class MyAbstractClass:
def my_abstract_method(self):
raise NotImplementedError("子类必须实现这个方法")
class MyConcreteClass(MyAbstractClass):
def my_abstract_method(self):
# 实现具体的方法
pass
当然二元操作符方法也可以抛出这个异常。
class MyClass:
def __init__(self, value):
self.value = value
def __add__(self, other):
if isinstance(other, MyClass):
return MyClass(self.value + other.value)
elif isinstance(other, int):
return MyClass(self.value + other)
else:
raise NotImplementedError
def __str__(self):
return str(self.value)
a = MyClass(3)
b = 2
c = a + b # c 的值为 5,因为处理了 int 类型
d = a + "test" # 会报 NotImplementedError,因为抛出了这个异常
对比
那么为什么要同时有 NotImplemented 和 NotImplementedError 呢?它们有什么区别呢?
看看以下代码:
class A:
def __init__(self, value):
self.value = value
def __eq__(self, other):
if isinstance(other, A):
# 只能和 A 类型进行比较
return self.value == other.value
else:
return NotImplemented
class B:
def __init__(self, value):
self.value = value
def __eq__(self, other):
if isinstance(other, A):
# 支持和 A 类型进行比较
return self.value == other.value
elif isinstance(other, B):
return self.value == other.value
else:
return NotImplemented
a = A(3)
b = B(3)
print(a == b) # True
c = B(2)
print(a == c) # False
在类 A 上并没有定义与 B 类型的比较方法,但是却并没有报错,而是执行了 B 的判断方法。这就是 NotImplemented 对象的作用。 它向解释器发出一个信号,告诉解释器如果当前操作失败,它应该再检查一下其他可行方法。例如在 a == b 表达式,如果 a.__eq__(b)
返回 NotImplemented,那么 Python 会尝试 b.__eq__(a)
。如果调用 b 的 __eq__()
方法可以返回 True 或者 False,那么该表达式就成功了。如果 b.__eq__(a)
也不能得出结果,那么 Python 会继续尝试其他方法,例如使用 != 来比较。
因此,NotImplemented 对象和 NotImplementedError 异常适用于两个不同的场景。NotImplemented 用于部分二元重载操作符方法,可以让解释器尝试找到最适合的方法来计算结果,特别是对于一些三方的类和我们自己的类进行操作,我们就不需要修改它们的源码,在我们自己的类中添加对应的处理逻辑即可。而 NotImplementedError 异常则用于抽象类的抽象方法中,用于告诉子类,这个方法必须要覆盖。