提问人:Alexander Soare 提问时间:8/10/2023 最后编辑:Alexander Soare 更新时间:8/10/2023 访问量:43
为什么 Python 无法推断出我的类遵循 Sequence 协议?
Why can't Python infer that my class follows the Sequence protocol?
问:
我希望如果我编写一个按照 https://docs.python.org/3.10/library/collections.abc.html 实现所需的所有方法的类,Python 将使用鸭子类型来知道它的实例是 Sequence,但我发现情况并非如此:Sequence
from collections.abc import Sequence
class MySequence:
def __getitem__(self, ix):
pass
def __iter__(self):
pass
def __len__(self):
pass
def __contains__(self, val):
pass
def __reversed__(self):
pass
def count(self, val):
pass
def index(self, val):
pass
seq = MySequence()
print(isinstance(seq, Sequence))
这将打印 False 而不是 True。为什么?
答:
4赞
wim
8/10/2023
#1
这里没有鸭子打字。如果你根本没有从 abc 继承,那么你需要注册你的类:Sequence
Sequence.register(MySequence)
从文档中关于鸭子打字的第 3 点:
一些简单的接口可以通过所需方法的存在直接识别
...
复杂接口不支持最后一种技术,因为接口不仅仅是方法名称的存在。接口指定方法之间的语义和关系,这些语义和关系不能仅从特定方法名称的存在中推断出来。例如,知道一个类提供 、 和 不足以区分 a 和 。
__getitem__
__len__
__iter__
Sequence
Mapping
评论
2赞
Brian61354270
8/10/2023
您可以参考的另一个文档链接:docs.python.org/3/glossary.html#term-sequence。“collections.abc.Sequence 抽象基类定义了一个更丰富的接口......实现此扩展接口的类型可以使用 register() 显式注册。
0赞
Alexander Soare
8/10/2023
好吧,所以我想这个解释仍然为返回 True(确实如此)留下了空间,对吧?因为也许不是一个“复杂的界面”。isinstance(seq, Container)
Container
0赞
wim
8/10/2023
右。它应该是不需要注册的实例。collections.abc.Iterable
0赞
Alexander Soare
8/10/2023
需要明确的是,你只是想写吗?不知道从哪里来。abc.Container
abc.Iterable
3赞
Brian61354270
8/10/2023
@AlexanderSoare我认为 wim 只是提供了一个不需要注册的 ABC 的例子。事实上,此表中标有脚注的任何 ABC 都不需要显式注册。[1]
评论
def __getitem__(self):
不兼容(甚至不可用?查看object.__getitem__
Sequence