【问题标题】:issubclass of abstract base class Sequence是抽象基类序列的子类
【发布时间】:2016-01-21 15:38:45
【问题描述】:

This list 显示了您需要实现哪些方法才能将您的类“视为”为序列:__getitem____len____contains____iter____reversed__index 和 @ 987654329@。那么为什么这个最小实现不起作用,即为什么issubclass(S, Sequence) is False

from collections import *


class S(object):
    def __getitem__(self, item):
        raise IndexError

    def __len__(self):
        return 0

    def __contains__(self, item):
        return False

    def __iter__(self):
        return iter(())

    def __reversed__(self):
        return self

    def index(self, item):
        raise IndexError

    def count(self, item):
        return 0


issubclass(S, Iterable)   # True  :-)
issubclass(S, Sized)      # True  :-)
issubclass(S, Container)  # True  :-)
issubclass(S, Sequence)   # False :-(

是否有我忽略的其他方法需要实现?我误解了抽象基类吗?继承 Sequence 使 issubclass 返回 True 当然,但这有点违背 abc 背后的想法,不是吗?

【问题讨论】:

  • 仅仅因为一个类实现了序列接口并不能使它成为序列的子类。
  • 我认为 OP 已经知道这一点。见abc
  • 对我来说,在 Python 中通俗地认为是序列(__len____getitem__ 带整数)与语言正式认为是序列(根据insinstance)之间似乎存在脱节)。就目前而言,您无法查看对象的方法并决定它是否正式被视为序列,这对我来说很奇怪。

标签: python subclassing duck-typing isinstance abstract-base-class


【解决方案1】:

Use the source, Luke!

Sequence 没有实现自己的__subclasshook__,所有来自Sequence 的父级的__subclasshook__ 实现都有这样的检查:

class Iterable:
    ...

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Iterable:  # <<<<
            if _hasattr(C, "__iter__"):
                return True
        return NotImplemented

但是,您可以将您的班级明确地register() 指定为Sequence

Sequence.register(S)

至于Sequence 没有实现__subclasshook__ 的原因,参见issue 16728(最初的标题是“collections.abc.Sequence 应该提供__subclasshook__”)。这个问题可以总结为一个序列可以是很多东西,这取决于使用它的人的需要:

许多需要序列的算法只需要__len____getitem__。 [...]collections.abc.Sequence 是一个更丰富的界面。

【讨论】:

  • 换句话说,collections.Sequence 是没有意义的(/不完整),除非用作 mixin?
  • @Kay:它为您提供了许多其他抽象基类的功能:如果您尝试在未定义所有必需方法的情况下进行继承,则会出现异常,并且您可以显式 register() 任意子类跨度>
  • 嗯,老实说,这似乎是 Python 黑客的公然疏忽。你知道Sequence.__subclasshook__没有实现的原因吗?
  • @Kay:__subclasshook__ 有点无意义。示例:拥有__iter__ 属性并不意味着实例已正确实现了可迭代对象。
  • 谢谢!现在我明白了这个问题。
猜你喜欢
  • 1970-01-01
  • 2017-01-08
  • 1970-01-01
  • 2018-07-11
  • 1970-01-01
  • 2013-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多