美文网首页
Python 序列类型 (2) - 序列类型的协议

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

作者: DejavuMoments | 来源:发表于2018-12-01 18:29 被阅读12次

    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
    

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

    相关文章

      网友评论

          本文标题:Python 序列类型 (2) - 序列类型的协议

          本文链接:https://www.haomeiwen.com/subject/cizlcqtx.html