• 第五章自定义序列类


    1.序列类型的分类

    • 容器序列(元素类型可以不同):list、tuple、deque
    • 扁平序列(元素类型必须相同):str、bytes、bytearray、array.array
    • 可变序列(序列内容可以修改):list、deque、bytearray、array
    • 不可变(序列内容不可以修改):str、tuple、bytes

    2.序列的abc继承关系

    • Sequence就是不可变序列的方法集合的抽象基类
    • MutableSequence是集合了可变序列的方法和协议的抽象基类。

    3.序列的+、+=和extend的区别

    • +:加号两边都是相同的类型,并且返回一个新的对象
    • +=:右侧只要是一个可迭代类型即可,不会返回一个新对象
      • +=内部调用魔法函数__iadd__,__iadd__内部调用extend函数遍历添加的对象放入左侧对象中

    补充:extend和append函数区别

    • extend:遍历元素一个一个放入其中
    • append:直接放入其中变成嵌套
     1 a = [1, 2]
     2 c = a + [3, 4]  # +:只能相同类型,产生新对象
     3 print(c)        # [1, 2, 3, 4]
     4 
     5 a += (3, 4)  # +=:可以不同类型
     6 print(a)     # [1, 2, 3, 4]
     7 
     8 b = [10, 11]
     9 b.extend((13, 14))
    10 print(b)    # [10, 11, 13, 14]
    11 
    12 b.append((1, 2))
    13 print(b)    # [10, 11, 13, 14, (1, 2)]

    4.实现可切片的对象

    • list的切片:
      • 模式:[start:end:step]
      • 解释:
        • 第一个数字start表示切片开始的位置,默认0
        • 第二个数字end表示切片截止的位置,不包含end的数据
        • 第三个数字step表示切片的步长,默认1
        • 当start为0时可以省略,当end为列表长度时可以省略
        • 当step为1时可以省略,省略步长时可以同时省略最后一个冒号
        • 当step为负整数时,表示反向切片,这时候start应该比end的值要大才行
     1 aList = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
     2 print(aList[::])  # 返回包含原列表中所有元素的新列表
     3 print(aList[::-1])  # 返回包含原列表中所有元素的逆序列表
     4 print(aList[::2])  # 隔一个取一个,获取偶数位置的元素
     5 print(aList[1::2])  # 隔一个取一个,获取奇数位置的元素
     6 print(aList[3:6])  # 指定切片的开始和结束位置
     7 aList[0:100]  # 切片结束位置大于列表长度时,从列表尾部截断
     8 aList[100:]  # 切片开始位置大于列表长度时,返回空列表
     9 
    10 aList[len(aList):] = [9]  # 在列表尾部增加元素
    11 aList[:0] = [1, 2]  # 在列表头部插入元素
    12 aList[3:3] = [4]  # 在列表中间位置插入元素
    13 aList[:3] = [1, 2]  # 替换列表元素,等号两边的列表长度相等
    14 aList[3:] = [4, 5, 6]  # 等号两边的列表长度也可以不相等
    15 aList[::2] = [0] * 3  # 隔一个修改一个
    16 print(aList)
    17 aList[::2] = ['a', 'b', 'c']  # 隔一个修改一个
    18 aList[::2] = [1, 2]  # 左侧切片不连续,等号两边列表长度必须相等
    19 aList[:3] = []  # 删除列表中前3个元素
    20 
    21 del aList[:3]  # 切片元素连续
    22 del aList[::2]  # 切片元素不连续,隔一个删一个
    • 实现对象切片:
      1. 重写__getitem__魔法函数
      2. 获得当前的类名
      3. 判断传入的参数是int类型还是slice类型
      4. int类型返回元素,切片类型返回对象
     1 import numbers
     2 
     3 
     4 class Group:
     5     # 支持切片操作
     6     def __init__(self, group_name, company_name, staffs):
     7         self.group_name = group_name
     8         self.company_name = company_name
     9         self.staffs = staffs
    10 
    11     def __reversed__(self):
    12         self.staffs.reverse()
    13 
    14     # 因为object[] 和 object[::]都会调动这个方法
    15     def __getitem__(self, item):
    16         # 取到class
    17         cls = type(self)
    18         # 判断传递进来的是slice类型还是int类型,返回不同的类型和操作,
    19         if isinstance(item, slice):
    20             return cls(group_name=self.group_name, company_name=self.company_name,
    21                        staffs=self.staffs[item])  # staffs = sel.staffs[:2] = ['wzh1', '123']
    22         if isinstance(item, numbers.Integral):
    23             return self.staffs[item]
    24 
    25     def __iter__(self):
    26         return iter(self.staffs)
    27 
    28     def __len__(self):
    29         return len(self.staffs)
    30 
    31     def __str__(self):
    32         return '组员有:{}'.format(self.staffs)
    33 
    34     def __contains__(self, item):
    35         if item in self.staffs:
    36             return True
    37         else:
    38             return False
    39 
    40 
    41 st = ['wzh1', '123', '456', '789']
    42 group = Group('A', 'TR', staffs=st)
    43 sub_group = group[:2]  # 这里会调用__getitem__魔法函数
    44 print(group)  # 这里会调用__str__魔法函数
    45 print(sub_group)  # 这里会调用__str__魔法函数
    46 
    47 if 'A' in group:  # 这里会调用__contains__魔法函数
    48     print('yes')
    49 
    50 for i in group:  # 这里会调用__iter__魔法函数
    51     print(i)
    52 
    53 reversed(group)  # 实际上是调用了__reversed__魔法函数
    54 print(group)  # 这里会调用__str__魔法函数

    5.bisect管理可排序序列

    • 概念:用来处理已经排序的序列,并且可以维护已经排序的序列,只使用升序排列
    • 查找方式:二分查找
    • 拥有属性和函数
      • 属性:
        • bisect:返回会插入的位置,默认为bisect_right,相同数字默认放入右侧
        • insort:直接插入的位置,默认为insort_right,相同数字默认插入右侧
      • 函数:
        • insort_right:直接插入的位置,相同数字右侧
        • insort_left:直接插入的位置,相同数字左侧
        • bisect_right:返回会插入的位置,相同数字为右侧
        • bisect_left:返回会插入的位置,相同数字为左侧
     1 import bisect
     2 from collections import deque
     3 
     4 # 用来处理已排序的序列,用来维持已排序的序列, 升序
     5 # 二分查找
     6 inter_list = deque()
     7 bisect.insort(inter_list, 3)
     8 bisect.insort(inter_list, 2)
     9 bisect.insort(inter_list, 5)
    10 bisect.insort(inter_list, 1)
    11 bisect.insort(inter_list, 6)
    12 
    13 print(bisect.bisect_left(inter_list, 3.0))   # 2
    14 print(bisect.bisect(inter_list, 3.0))        # 3
    15 print(bisect.bisect_right(inter_list, 3.0))  # 3
    16 bisect.insort_left(inter_list, 3.0)
    17 # 学习成绩
    18 print(inter_list)   # deque([1, 2, 3.0, 3, 5, 6])

    6.什么时候我们不该用列表

    • array和list的区别:
      • array:只能放入相同的指定类型的数据,内存空间连续
      • list:可以放入不同类型的数据,内存空间不连续

    1 my_array = array.array("i")
    2 my_array.append(1)
    3 my_array.append("abc")  # 报错

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

    • 使用范围:尽量保持可读性,不要太过复杂
    • 优点:效率高,简洁
    • 使用语法:
      • list:
        • 使用中括号[]:[表达式 for 变量 in 列表]    或者  [表达式 for 变量 in 列表 if 条件]
      • generator:
        • 使用小括号():(表达式 for 变量 in 列表)    或者  (表达式 for 变量 in 列表 if 条件)
      • dict:
        • 使用花括号{}:{表达式 for 变量 in 列表}    或者  {表达式 for 变量 in 列表 if 条件}
     1 # 列表推导式
     2 # 1.提取出1-20之间的奇数
     3 odd_list = []
     4 for i in range(21):
     5     if i % 2 == 1:
     6         odd_list.append(i)
     7 print(odd_list)
     8 
     9 # 使用列表推导式
    10 odd_list = [x for x in range(21) if x % 2 == 1]
    11 print(odd_list)
    12 
    13 
    14 # 列表推导式的格式
    15 # [on True for x in iteralbe 条件表达式(过滤)]
    16 
    17 # 逻辑复杂的情况
    18 def handle_item(item):
    19     return item * item
    20 
    21 
    22 odd_list = [handle_item(x) for x in range(21) if x % 2 == 1]
    23 print(odd_list)
    24 # 列表表达式的前面可以是一个函数,也可以是一个函数,但是不能是匿名函数
    25 
    26 # 生成器表达式,将列表推导式的[]改成(),就变成了生成器表达式
    27 gen = (x for x in range(21) if x % 2 == 1)
    28 print(gen)  # <generator object <genexpr> at 0x000001CF1B01C8E0>
    29 print(type(gen))  # <class 'generator'>
    30 for item in gen:
    31     print(item)
    32 
    33 # 字典推导式,颠倒key和value
    34 my_dict = {'bob1': 22, 'bob3': 23, 'bob4': 5}
    35 
    36 reversed_dict = {value: key for key, value in my_dict.items()}
    37 print(reversed_dict)
    38 
    39 # 集合推导式 set
    40 # 如何将一个字典的key全部放到一个集合当中.
    41 my_set = {key for key in my_dict.keys()}
    42 # 也可以使用
    43 my_set = set(my_dict.keys())
    44 print(type(my_set))
    45 print(my_set)
  • 相关阅读:
    PostgreSQL操作问题(转载)
    psql执行的时候不输入密码的设定 (转载)
    项目管理——对事不对人(转载)
    软件项目经理应有的能力和素质(转载)
    Postgresql数据库的一些字符串操作函数
    8 of the best web design resource pages(转载)
    再谈:Word转PDF及SWF在线浏览——Flash Paper
    项目VS产品
    PostgreSQL+PostGIS的使用(转载)
    12+ open source projects for .NET you probably didn’t know about(转载)
  • 原文地址:https://www.cnblogs.com/zhihaospace/p/12075620.html
Copyright © 2020-2023  润新知