抽象基类与鸭子类型

koj*_*iro 5 python idioms duck-typing

Python 具有针对容器类型的特定ABC。它说它们是,“……用于测试一个类是否提供了特定的接口。” (而且它们对某些 mixin 也很有用,但我们暂时先忽略它。)

我很难弄清楚为什么这些 ABC 中的一些真的很有用。也许我的问题只是文档中的例子太学术了,但使用这些例子:

# Verbatim
size = None
if isinstance(myvar, collections.abc.Sized):
    size = len(myvar)

# Is that so much better than
size = None
if hasattr(myvar, '__len__'):
    size = len(myvar)
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,您避免导入并且代码对我来说似乎更明确。你可以从它的名字中推断出 collections.abc.Sized 的含义,或者查找它,但它并不像“如果它有长度,就得到它的长度”那样明确。

集合类型测试的 abc 方法真的比显式hasattr测试更符合 Python 习惯吗?如果是,为什么?(不单纯比复杂好王牌明确优于隐含在这种情况下?)

Chr*_*son 5

您可以使用任何一种方法获得相同的结果。ABC 方法的主要好处是为您提供了一些逻辑。例如,要通过鸭子类型实现 Set 类型,您必须编写和测试 14 个接口 - __contains__, __iter__, __len__, __le__, __lt__, __eq__, __ne__, __gt__, __ge__, __and__, __or__, __sub__, __xor__, and isdisjoint

但是,如果您使用 ABC,您只需要定义__contains__, __iter__ and __len__- ABC 使用您提供的这些功能来为您实现剩余的 11 个方法。ABC 会做你会做的事情,但工作量更少。这是一条捷径,可让您到达同一目的地。


小智 1

对我来说,mixin 似乎是这个模块的主要部分。同样在大多数情况下,是的,简单是编写完美代码的主要目标,至少对我来说(不是我曾经管理过它)。事实上,ABC 模块的功能似乎非常清楚它们的作用,这有助于共享和浏览代码。最后,我对此可能是错的,所以不要指望它,尽管我认为 ABC 的某些函数可以在一个函数中检查多个属性。