返回介绍

11.5 定义抽象基类的子类

发布于 2024-02-05 21:59:47 字数 2327 浏览 0 评论 0 收藏 0

我们将遵循 Martelli 的建议,先利用现有的抽象基类(collections.MutableSequence),然后再斗胆自己定义。在示例 11-8 中,我们明确把 FrenchDeck2 声明为 collections.MutableSequence 的子类。

示例 11-8 frenchdeck2.py:FrenchDeck2,collections.MutableSequence 的子类

import collections

Card = collections.namedtuple('Card', ['rank', 'suit'])

class FrenchDeck2(collections.MutableSequence):
  ranks = [str(n) for n in range(2, 11)] + list('JQKA')
  suits = 'spades diamonds clubs hearts'.split()

  def __init__(self):
    self._cards = [Card(rank, suit) for suit in self.suits
                    for rank in self.ranks]

  def __len__(self):
    return len(self._cards)

  def __getitem__(self, position):
    return self._cards[position]

  def __setitem__(self, position, value):  # ➊
    self._cards[position] = value

  def __delitem__(self, position):  # ➋
    del self._cards[position]

  def insert(self, position, value):  # ➌
    self._cards.insert(position, value)

❶ 为了支持洗牌,只需实现 __setitem__ 方法。

❷ 但是继承 MutableSequence 的类必须实现 __delitem__ 方法,这是 MutableSequence 类的一个抽象方法。

❸ 此外,还要实现 insert 方法,这是 MutableSequence 类的第三个抽象方法。

导入时(加载并编译 frenchdeck2.py 模块时),Python 不会检查抽象方法的实现,在运行时实例化 FrenchDeck2 类时才会真正检查。因此,如果没有正确实现某个抽象方法,Python 会抛出 TypeError 异常,并把错误消息设为"Can't instantiate abstract class FrenchDeck2 with abstract methods __delitem__, insert"。正是这个原因,即便 FrenchDeck2 类不需要 __delitem__ 和 insert 提供的行为,也要实现,因为 MutableSequence 抽象基类需要它们。

如图 11-2 所示,Sequence 和 MutableSequence 抽象基类的方法不全是抽象的。

图 11-2:MutableSequence 抽象基类和 collections.abc 中它的超类的 UML 类图(箭头由子类指向祖先;以斜体显示的名称是抽象类和抽象方法)

FrenchDeck2 从 Sequence 继承了几个拿来即用的具体方法:__contains__、__iter__、__reversed__、index 和 count。FrenchDeck2 从 MutableSequence 继承了 append、extend、pop、remove 和__iadd__。

在 collections.abc 中,每个抽象基类的具体方法都是作为类的公开接口实现的,因此不用知道实例的内部结构。

 要想实现子类,我们可以覆盖从抽象基类中继承的方法,以更高效的方式重新实现。例如,__contains__ 方法会全面扫描序列,可是,如果你定义的序列按顺序保存元素,那就可以重新定义 __contains__ 方法,使用 bisect 函数做二分查找(参见 2.8 节),从而提升搜索速度。

为了充分使用抽象基类,我们要知道有哪些抽象基类可用。接下来介绍集合抽象基类。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文