• 第四章:Python-高级编程-自定义序列类


    第四章:Python-高级编程-自定义序列类

    Python3高级核心技术97讲 笔记

    4.1 Python中的序列分类

    4.1.1 容器序列

    """
    list tuple deque 可以放入任意类型的数据
    """
    

    4.1.2 扁平序列

    """
    str bytes bytearray array.array
    注意array与list的区别,array存放数据
    类型需一致。
    """
    

    4.1.3 可变序列

    """
    list deque bytearry array
    """
    

    4.1.4 不可变

    """
    str tuple bytes
    """
    

    4.2 Python中序列类型的abc继承关系

    """
    需要知道的是,在Python中,其跟容器相关的数据结构
    的抽象基类是放在collection.abc模块下的
    """
    
    """
    可变序列类型主要使用了
    __setitem__
    __delitem__
    等魔法函数
    """
    
    __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",
               ]
    
    
    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
        
        
    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.
    
               Supporting start and stop arguments is optional, but
               recommended.
            '''
            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)
        
        
     class MutableSequence(Sequence):
    
        __slots__ = ()
    
        """All the operations on a read-write sequence.
    
        Concrete subclasses must provide __new__ or __init__,
        __getitem__, __setitem__, __delitem__, __len__, and insert().
    
        """
    
        @abstractmethod
        def __setitem__(self, index, value):
            raise IndexError
    
        @abstractmethod
        def __delitem__(self, index):
            raise IndexError
    
        @abstractmethod
        def insert(self, index, value):
            'S.insert(index, value) -- insert value before index'
            raise IndexError
    
        def append(self, value):
            'S.append(value) -- append value to the end of the sequence'
            self.insert(len(self), value)
    
        def clear(self):
            'S.clear() -> None -- remove all items from S'
            try:
                while True:
                    self.pop()
            except IndexError:
                pass
    
        def reverse(self):
            'S.reverse() -- reverse *IN PLACE*'
            n = len(self)
            for i in range(n//2):
                self[i], self[n-i-1] = self[n-i-1], self[i]
    
        def extend(self, values):
            'S.extend(iterable) -- extend sequence by appending elements from the iterable'
            for v in values:
                self.append(v)
    
        def pop(self, index=-1):
            '''S.pop([index]) -> item -- remove and return item at index (default last).
               Raise IndexError if list is empty or index is out of range.
            '''
            v = self[index]
            del self[index]
            return v
    
        def remove(self, value):
            '''S.remove(value) -- remove first occurrence of value.
               Raise ValueError if the value is not present.
            '''
            del self[self.index(value)]
    
        def __iadd__(self, values):
            self.extend(values)
            return self   
    
    

    4.3 list中extend方法区别

    a = [1, 2]
    c = a + [3, 4]
    print(c)
    
    a += [3, 4]
    print(a)
    a += (5, 6)  # 不报错
    print(a)
    c = a + (7, 8)  # 报错
    
    """
    为什么会有这种差别,
    实际上在 += 时,Python
    实现的魔法函数是 __iadd__
    ,调用这个魔法函数实际就是把
    += 右边的值传入 list 的 extend方法。
    """
    
    """
    注意append的方法与extend的方法
    append会将参数作为整个。extend会将
    参数分开。
    """
    

    4.4 实现可切片的对象

    #模式[start:end:step]
    """
        其中,第一个数字start表示切片开始位置,默认为0;
        第二个数字end表示切片截止(但不包含)位置(默认为列表长度);
        第三个数字step表示切片的步长(默认为1)。
        当start为0时可以省略,当end为列表长度时可以省略,
        当step为1时可以省略,并且省略步长时可以同时省略最后一个冒号。
        另外,当step为负整数时,表示反向切片,这时start应该比end的值要大才行。
    """
    aList = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
    print (aList[::])  # 返回包含原列表中所有元素的新列表
    print (aList[::-1])  # 返回包含原列表中所有元素的逆序列表
    print (aList[::2])  # 隔一个取一个,获取偶数位置的元素
    print (aList[1::2])  # 隔一个取一个,获取奇数位置的元素
    print (aList[3:6])  # 指定切片的开始和结束位置
    aList[0:100]  # 切片结束位置大于列表长度时,从列表尾部截断
    aList[100:]  # 切片开始位置大于列表长度时,返回空列表
    
    aList[len(aList):] = [9]  # 在列表尾部增加元素
    aList[:0] = [1, 2]  # 在列表头部插入元素
    aList[3:3] = [4]  # 在列表中间位置插入元素
    aList[:3] = [1, 2]  # 替换列表元素,等号两边的列表长度相等
    aList[3:] = [4, 5, 6]  # 等号两边的列表长度也可以不相等
    aList[::2] = [0] * 3  # 隔一个修改一个
    print (aList)
    aList[::2] = ['a', 'b', 'c']  # 隔一个修改一个
    aList[::2] = [1,2]  # 左侧切片不连续,等号两边列表长度必须相等
    aList[:3] = []  # 删除列表中前3个元素
    
    del aList[:3]  # 切片元素连续
    del aList[::2]  # 切片元素不连续,隔一个删一个
    
    
    """
    编写支持切片的对象
    """
    
    
    import numbers
    class Group:
        #支持切片操作
        def __init__(self, group_name, company_name, staffs):
            self.group_name = group_name
            self.company_name = company_name
            self.staffs = staffs
    
        def __reversed__(self):
            self.staffs.reverse()
    
        def __getitem__(self, item):
            cls = type(self)
            if isinstance(item, slice):
                return cls(group_name=self.group_name, company_name=self.company_name, staffs=self.staffs[item])
            elif isinstance(item, numbers.Integral):
                return cls(group_name=self.group_name, company_name=self.company_name, staffs=[self.staffs[item]])
    
        def __len__(self):
            return len(self.staffs)
    
        def __iter__(self):
            return iter(self.staffs)
    
        def __contains__(self, item):
            if item in self.staffs:
                return True
            else:
                return False
    
    staffs = ["bobby1", "imooc", "bobby2", "bobby3"]
    group = Group(company_name="imooc", group_name="user", staffs=staffs)
    reversed(group)
    for user in group:
        print(user)
        
    

    4.5 什么时候我们不该使用列表

    # array, deque
    # 数组
    
    
    import array
    # array和list的一个重要区别,array只能存放指定的类型
    my_array = array.array("i")
    my_array.append(1)
    my_array.append("abc")
    
    

    4.6 列表推导式、生成器表达式、字典推导式

    # 列表生成式(列表推导式)
    # 提取出1-20之间的奇数
    
    odd_list = []
    for i in range(21):
        if i%2 == 1:
            odd_list.append(i)
            
    odd_list = [i for i in range(21) if i%2 == 1]
    
    
    # 逻辑复杂的情况
    def handle_item(item):
        return item * item
    
    
    odd_list = [handle_item(i) for i in range(21) if i%2 == 1]
    
    # 列表生成式性能比列表操作高
    
    
    # 生成器表达式
    odd_gen = (i for i in range(21) if i%2 == 1)
    print(type(odd_list))
    
    
    # 字典推导式
    my_dict = {"bobby1":22, "bobby2":23, "imooc.com":5}
    reversed_dict = {value:key for key, value in my_dict.items()}
    
    
    # 集合推导式
    my_set = {key for key, value in my_dict.items()}
    print(type(my_set))
    
    my_set = set(my_dict.keys())  # 不够灵活
    
  • 相关阅读:
    OTA JAR和JAD的mime不同
    document.getElementById('selCatalog').remove(i)突然无效???!
    判断WAP1.1和WAP2.0并解析为wml或xhtml
    IE和firefox下显示html内容
    unixrisk tip
    unixftp windows
    unixstdin/stdout/stderr
    峰鸟摄影
    linuxgrep commond
    unixtutorial(recommended)
  • 原文地址:https://www.cnblogs.com/xunjishu/p/12851495.html
Copyright © 2020-2023  润新知