【问题标题】:How exactly does Python ABC interface work?Python ABC 接口究竟是如何工作的?
【发布时间】:2021-08-13 14:40:40
【问题描述】:

我正在阅读 Luciano Ramalho 的《Fluent Python》一书,我遇到了以下行:

请注意,内置的具体序列类型实际上并不 继承 Sequence 和 MutableSequence 抽象基类 (ABC) 描绘

所以我从 Python 文档中查看了 ABC,但我在理解它们的目的时遇到了问题。

例如,isinstance([], abc.Iterable) 对于列表返回 Trueabc.Sequenceabc.MutableSequence 也是如此,这是有道理的。对于isinstanceissubclass 方法,以下内容也是如此。

issubclass(str, abc.MutableSequence) --> False
isinstance((), abc.MutableSequence)  --> False

如果我执行以下操作:

class A:
    def __iter__(self):
        pass

a = A()
isinstance(a, abc.Iterable) # True
issubclass(A, abc.Iterable) # True

但是 A 没有在其类定义中继承 abc.Iterable (并且,根据本书,我假设前面提到的其他类也没有)。 issubclass / isinstance 方法和 ABC 接口如何在这里工作? 这些函数是否只是在类定义中查找 dunder 方法签名并将它们与上述 ABC 类中的 dunder 签名匹配?

除了提供一种验证一个类是否包含某些特定的 dunder 方法的方法之外,我看不出 ABC 类的任何目的,所以很高兴能更多地了解整个过程的目的。

我们将不胜感激任何形式的帮助。谢谢。

【问题讨论】:

  • 确实可以不使用 ABC 编写 Python 类,只依赖鸭子类型。你可以在这里找到更多关于为什么要使用 ABC 的讨论:stackoverflow.com/questions/3570796/…
  • 这能回答你的问题吗? Why use Abstract Base Classes in Python?
  • 虽然在 collections.abc.Iterable 的情况下,您可以简单地检查 MRO 中是否存在 __iter__,但我认为 isinstance(a, abc.Iterable) 是一种更好的说法,“我'即将迭代这个对象,让我先检查一下我是否可以做到这一点”。它在类型提示的世界中变得更加有用。

标签: python python-3.x inheritance abc


【解决方案1】:

Iterable 定义了__subclasshook__ 类方法,如果该类有__iter__ 方法,则返回True

@classmethod
def __subclasshook__(cls, C):
    if cls is Iterable:
        return _check_methods(C, "__iter__")
    return NotImplemented

a 可以通过两种方式成为b 的子类。 a 可以继承自b(或b 的子类),或者b.__subclasshook__(a) 可以返回True

由于isinstance(a, b) 检查type(a) 是否是b 的子类,它也受__subclasshook__ 定义的影响。

【讨论】:

    猜你喜欢
    • 2015-02-19
    • 2013-10-28
    • 1970-01-01
    • 2015-12-02
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 2014-12-16
    相关资源
    最近更新 更多