Python 序列类型 (2) - 序列类型的协议

Python 中,collections.abc 模块下有很多和容器相关的一些数据结构的抽象基类。

__all__ 中定义了和 collection 相关的基类,属于内置的抽象基类。

# Copyright 2007 Google, Inc. All Rights Reserved.
# Licensed to PSF under a Contributor Agreement.

"""Abstract Base Classes (ABCs) for collections, according to PEP 3119.

Unit tests are in test_collections.
"""

from abc import ABCMeta, abstractmethod
import sys

__all__ = ["Awaitable", "Coroutine",
           "AsyncIterable", "AsyncIterator", "AsyncGenerator",
           "Hashable", "Iterable", "Iterator", "Generator", "Reversible",
           "Sized", "Container", "Callable", "Collection",
           "Set", "MutableSet",
           "Mapping", "MutableMapping",
           "MappingView", "KeysView", "ItemsView", "ValuesView",
           "Sequence", "MutableSequence",
           "ByteString",
           ]

# This module has been renamed from collections.abc to _collections_abc to
# speed up interpreter startup. Some of the types such as MutableMapping are
# required early but collections module imports a lot of other modules.
# See issue #19218
__name__ = "collections.abc"

在这里,我们主要关注 "Sequence" 和 "MutableSequence",分别为不可变的序列类型和不可变的序列类型。

先来看看 "Sequence",其继承了 Reversible, Collection 基类

### SEQUENCES ###
class Sequence(Reversible, Collection):

    """All the operations on a read-only sequence.

    Concrete subclasses must override __new__ or __init__,
    __getitem__, and __len__.
    """

    __slots__ = ()

    @abstractmethod
    def __getitem__(self, index):
        raise IndexError

    def __iter__(self):
        i = 0
        try:
            while True:
                v = self[i]
                yield v
                i += 1
        except IndexError:
            return

    def __contains__(self, value):
        for v in self:
            if v is value or v == value:
                return True
        return False

    def __reversed__(self):
        for i in reversed(range(len(self))):
            yield self[i]

    def index(self, value, start=0, stop=None):
        '''S.index(value, [start, [stop]]) -> integer -- return first index of value.
           Raises ValueError if the value is not present.
        '''
        if start is not None and start < 0:
            start = max(len(self) + start, 0)
        if stop is not None and stop < 0:
            stop += len(self)

        i = start
        while stop is None or i < stop:
            try:
                v = self[i]
                if v is value or v == value:
                    return i
            except IndexError:
                break
            i += 1
        raise ValueError

    def count(self, value):
        'S.count(value) -> integer -- return number of occurrences of value'
        return sum(1 for v in self if v is value or v == value)

Sequence.register(tuple)
Sequence.register(str)
Sequence.register(range)
Sequence.register(memoryview)

这是 Collection 基类的定义

class Collection(Sized, Iterable, Container):

    __slots__ = ()

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Collection:
            return _check_methods(C,  "__len__", "__iter__", "__contains__")
        return NotImplemented
class Reversible(Iterable):

    __slots__ = ()

    @abstractmethod
    def __reversed__(self):
        while False:
            yield None

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

Collection 继承了 Sized, Iterable, Container 三个基类

class Sized(metaclass=ABCMeta):

    __slots__ = ()

    # 实现了 __len__ 方法,可以获取其长度
    @abstractmethod
    def __len__(self):
        return 0

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

class Iterable(metaclass=ABCMeta):

    __slots__ = ()

    # 实现了__iter__方法,可以进行 for 循环
    @abstractmethod
    def __iter__(self):
        while False:
            yield None

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


class Container(metaclass=ABCMeta):

    __slots__ = ()
    
    # 实现了 __contains__,可以使用 if-in 模式判断。
    # Python 解释器首先使用 __contains__
    # 没有的话退一步找 __getitem__,然后遍历整个序列
    @abstractmethod
    def __contains__(self, x):
        return False

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

所以,在我们自己定义序列类型的时候,需要遵循这些协议。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 14,057评论 6 13
  • 花飞即花开,花开人自醉,此生来到此,只为同相遇。 ——题记 本来这...
    Stable阅读 1,783评论 0 2
  • 6.7日课“套娃现象”感悟: “你要是永远只任用比自己水平差的人,那么公司就会沦为侏儒,你要是敢于启用比自己水平高...
    合肥李风丽阅读 1,441评论 0 2
  • 这是百乐色彩雫彩墨试色的第三篇文章,这篇文章主要是朝颜,松露,雾草,夕烧,紫阳花,天色这六个颜色,这篇文章之后,关...
    nonozone阅读 11,917评论 1 9

友情链接更多精彩内容