提问人:Ali 提问时间:8/29/2023 更新时间:8/29/2023 访问量:34
Sequence 接口的实现不足以成为 Sequence
The implementation of Sequence interface is not sufficient to be a Sequence
问:
我注意到,在检查类是否是抽象类的实例时,鸭子类型在一定程度上效果相当好。
例如,要成为 的实例,我们只需要定义一个方法:collections.abc.Sized
__len__()
import collections.abc
class MySized:
def __len__(self):
return 0
assert isinstance(MySized(), collections.abc.Sized) # It is
同样,我们可以定义实现 、 、 等接口的类。Container
Iterable
Collection
当我试图写自己的.Sequence
根据文档以及 cpython 中的代码,a 应该是 a , a ,并且另外实现方法 和 。Sequence
Collection
Reversible
__getitem__()
index()
count()
但是鸭子打字是不够的:
import collections.abc
class MySequence:
def __getitem__(self, i):
return None
def __len__(self):
return 0
def __iter__(self):
return iter([])
def __reversed__(self):
return reversed([])
def __contains__(self, x):
return True
def index(self, value, start=0, stop=None):
return 0
def count(self, value):
return 0
assert isinstance(MySequence(), collections.abc.Collection) # Ok
assert isinstance(MySequence(), collections.abc.Reversible) # Ok
assert isinstance(MySequence(), collections.abc.Sequence) # Fail! It's not
当然,如果我们从抽象基类显式继承一个类,它就可以工作:
import collections.abc
class MySequence(collections.abc.Sequence):
def __getitem__(self, i):
return None
def __len__(self):
return 0
assert isinstance(MySequence(), collections.abc.Sequence) # It is
了解这种行为的原因以及接口实现的适用性限制会很有趣。也许我错过了其他一些未记录的方法?或者对于某些容器来说,它变得有必要从抽象的祖先显式继承?
答:
2赞
matszwecja
8/29/2023
#1
来自文档(强调我的):
接口的 or 测试在一个中工作 三种方式。
issubclass()
isinstance()
新编写的类可以直接从其中一个抽象继承 基类
现有类和内置类可以注册为“虚拟类” 子类”。
一些简单的界面可以直接识别 存在所需的方法(除非已设置这些方法) 更改为 )。复杂接口不支持最后一种技术,因为接口不仅仅是方法名称的存在。例如,知道一个类提供
__getitem__
、__len__
和__iter__
不足以将Sequence
与Mapping
区分开来。None
如果没有显式继承,您将依赖于案例 3,该案例被明确声明不适用于序列。
评论