python 3.x 自定义序列
自定义序列
- 序列是python中非常重要的协议(python基于协议来编程的)
- 与容器相关的数据结构,它的抽象基类都是放在collections下的abc模块
- abc下的_collections_abc的__all__中定义了collections相关的抽象基类
1 __all__ = ["Awaitable", "Coroutine", 2 "AsyncIterable", "AsyncIterator", "AsyncGenerator", 3 "Hashable", "Iterable", "Iterator", "Generator", "Reversible", 4 "Sized", "Container", "Callable", "Collection", 5 "Set", "MutableSet", 6 "Mapping", "MutableMapping", 7 "MappingView", "KeysView", "ItemsView", "ValuesView", 8 "Sequence", "MutableSequence", 9 "ByteString", 10 ]
与序列相关的抽象基类
Sequence(不可变的序列) --> class Sequence(Reversible, Collection):
- Reversible类源码
1 class Reversible(Iterable): 2 3 __slots__ = () 4 5 @abstractmethod 6 def __reversed__(self): 7 while False: 8 yield None 9 10 @classmethod 11 def __subclasshook__(cls, C): 12 if cls is Reversible: 13 return _check_methods(C, "__reversed__", "__iter__") 14 return NotImplemented
- Sized源码
1 class Sized(metaclass=ABCMeta): 2 3 __slots__ = () 4 5 @abstractmethod 6 def __len__(self): 7 return 0 8 9 @classmethod 10 def __subclasshook__(cls, C): 11 if cls is Sized: 12 return _check_methods(C, "__len__") 13 return NotImplemented
- Iterable源码
1 class Iterable(metaclass=ABCMeta): 2 3 __slots__ = () 4 5 @abstractmethod 6 def __iter__(self): 7 while False: 8 yield None 9 10 @classmethod 11 def __subclasshook__(cls, C): 12 if cls is Iterable: 13 return _check_methods(C, "__iter__") 14 return NotImplemented
- Container源码
1 class Container(metaclass=ABCMeta): 2 3 __slots__ = () 4 5 @abstractmethod 6 def __contains__(self, x): 7 return False 8 9 @classmethod 10 def __subclasshook__(cls, C): 11 if cls is Container: 12 return _check_methods(C, "__contains__") 13 return NotImplemented
- Collection源码
1 class Collection(Sized, Iterable, Container): 2 3 __slots__ = () 4 5 @classmethod 6 def __subclasshook__(cls, C): 7 if cls is Collection: 8 return _check_methods(C, "__len__", "__iter__", "__contains__") 9 return NotImplemented
- Sequence源码
1 class Sequence(Reversible, Collection): 2 3 """All the operations on a read-only sequence. 4 5 Concrete subclasses must override __new__ or __init__, 6 __getitem__, and __len__. 7 """ 8 9 __slots__ = () 10 11 @abstractmethod 12 def __getitem__(self, index): 13 raise IndexError 14 15 def __iter__(self): 16 i = 0 17 try: 18 while True: 19 v = self[i] 20 yield v 21 i += 1 22 except IndexError: 23 return 24 25 def __contains__(self, value): 26 for v in self: 27 if v is value or v == value: 28 return True 29 return False 30 31 def __reversed__(self): 32 for i in reversed(range(len(self))): 33 yield self[i] 34 35 def index(self, value, start=0, stop=None): 36 '''S.index(value, [start, [stop]]) -> integer -- return first index of value. 37 Raises ValueError if the value is not present. 38 ''' 39 if start is not None and start < 0: 40 start = max(len(self) + start, 0) 41 if stop is not None and stop < 0: 42 stop += len(self) 43 44 i = start 45 while stop is None or i < stop: 46 try: 47 v = self[i] 48 if v is value or v == value: 49 return i 50 except IndexError: 51 break 52 i += 1 53 raise ValueError 54 55 def count(self, value): 56 'S.count(value) -> integer -- return number of occurrences of value' 57 return sum(1 for v in self if v is value or v == value) 58 59 Sequence.register(tuple) 60 Sequence.register(str) 61 Sequence.register(range) 62 Sequence.register(memoryview)
通过以上的源码
- Sequence继承两个类Reversible, Collection
- Reversible: 中定义抽象魔法函数@abstractmethod >> def __reversed__(self): >> while False: >> yield None, 数据的反转 如: abc --> cba
- Collection: 继承三个类 --> class Collection(Sized, Iterable, Container):
- Sized( class Sized(metaclass=ABCMeta): )中定义了抽象魔法函数@abstractmethod >> def __len__(self): >> return 0,这样可以计算Collection的长度.
- Iterable( class Iterable(metaclass=ABCMeta): )中定义了抽象魔法函数@abstractmethod >> def __iter__(self): >> while False: >> yield None,这样可以对Collection进行迭代(for循环)
- Container( class Container(metaclass=ABCMeta): )中定义了抽象魔法函数@abstractmethod >> def __contains__(self, x): >> return False
有了__contains__()方法,可以使用if...in...来做判断,(比如说判断一个数据是否在list里面)
如果没有__contains__()魔法函数,但是定义了__getitem__()魔法函数,实际上也可以使用if...in..来进行判断.
- if...in...对python解释器来说,python解释器首选的就是Container中的__contains__()魔法函数,如果没有的话,退一步,去找__getitem__()魔法函数,然后通过__getitem__()魔法函数遍历整个序列(python在内部做了很多的优化)
- 通过查看Sequence的源码可以知道对于不可变序列类型来说,
- 继承Reversible实现抽象魔法函数__reversed__()
- 继承Collection.实现抽象魔法函数__contains__()和__iter__(),而抽象魔法函数__len__()需要Sequence的子类来实现
- Sequence中的抽象魔法函数__getitem__()需要子类来实现,以及构造函数__init__().
MutableSequence(可变的序列) --> class MutableSequence(Sequence):
- MutableSequence源码
1 class MutableSequence(Sequence): 2 3 __slots__ = () 4 5 """All the operations on a read-write sequence. 6 7 Concrete subclasses must provide __new__ or __init__, 8 __getitem__, __setitem__, __delitem__, __len__, and insert(). 9 10 """ 11 12 @abstractmethod 13 def __setitem__(self, index, value): 14 raise IndexError 15 16 @abstractmethod 17 def __delitem__(self, index): 18 raise IndexError 19 20 @abstractmethod 21 def insert(self, index, value): 22 'S.insert(index, value) -- insert value before index' 23 raise IndexError 24 25 def append(self, value): 26 'S.append(value) -- append value to the end of the sequence' 27 self.insert(len(self), value) 28 29 def clear(self): 30 'S.clear() -> None -- remove all items from S' 31 try: 32 while True: 33 self.pop() 34 except IndexError: 35 pass 36 37 def reverse(self): 38 'S.reverse() -- reverse *IN PLACE*' 39 n = len(self) 40 for i in range(n//2): 41 self[i], self[n-i-1] = self[n-i-1], self[i] 42 43 def extend(self, values): 44 'S.extend(iterable) -- extend sequence by appending elements from the iterable' 45 for v in values: 46 self.append(v) 47 48 def pop(self, index=-1): 49 '''S.pop([index]) -> item -- remove and return item at index (default last). 50 Raise IndexError if list is empty or index is out of range. 51 ''' 52 v = self[index] 53 del self[index] 54 return v 55 56 def remove(self, value): 57 '''S.remove(value) -- remove first occurrence of value. 58 Raise ValueError if the value is not present. 59 ''' 60 del self[self.index(value)] 61 62 def __iadd__(self, values): 63 self.extend(values) 64 return self 65 66 MutableSequence.register(list) 67 MutableSequence.register(bytearray) # Multiply inheriting, see ByteString
通过MutableSequence源码
- MutableSequence继承Sequence,所以MutableSequence的子类必须覆写Sequence类没有实现的抽象魔法函数__len__()和__getitem__().
- 以及MutableSequence类中的抽象魔法函数__setitem__()和__delitem__().以及抽象方法insert().以及构造函数__init__()
序列的+,+=和extend的区别
- + 运算符将两个列表合并且生成一个新的对象列表,新列表与原来合并的子列表互不影响.
- += 运算符内部实现了一个魔法函数__iadd__(self).
1 def __iadd__(self, values): 2 self.extend(values) 3 return self 4 5 # -------------------------------------------------------------------------------------- 6 7 def extend(self, values): 8 'S.extend(iterable) -- extend sequence by appending elements from the iterable' 9 for v in values: 10 self.append(v) 11 12 # -------------------------------------------------------------------------------------- 13 14 def append(self, value): 15 'S.append(value) -- append value to the end of the sequence' 16 self.insert(len(self), value) 17 18 # -------------------------------------------------------------------------------------- 19 20 @abstractmethod 21 def insert(self, index, value): 22 'S.insert(index, value) -- insert value before index' 23 raise IndexError
通过源码:
+= 运算符内部实现了一个魔法函数__iadd__(self).而__iadd__()魔法函数中调用extend()方法,extend()方法将传递进来的可迭代的数据,进行for循环遍历,
使用append(len(self),value)方法将可迭代的数据元素逐一添加到原有序列的后面append()函数内部调用insert()方法,insert()的意思是将插入的元素,放到指定索引值处
1 # 初始化list的两种方式 2 a = [1, 2] 3 # 空列表 4 b = list([9, 8]) 5 6 # 将两个列表相加并产生一个新的对象c,新列表与原来的子列表互不影响 7 c = a + [3, 4] 8 9 # 结果: [1, 2, 3, 4] 10 print(c) 11 12 # 报错: TypeError: can only concatenate list (not "tuple") to list 13 # 只能将list和list数据类型想合并. 14 # d = a + (11, 22) 15 16 # ------------------------------------------------------------------------ 17 18 # += 运算符实现两列表合并是在原有的列表上添加一个列表的所有元素 19 a += [5, 6] 20 # 结果: [1, 2, 5, 6] 21 print(a) 22 23 a += (11, 22) 24 # 结果: [1, 2, 5, 6, 11, 22] 25 print(a) 26 27 # ------------------------------------------------------------------------ 28 29 # extend() 与 append()区别 30 # extend()将传递进来的序列对象,进行for循环遍历,将元素逐一添加的原有列表中 31 # append()将传递进来的数据当成一个元素,添加到原有列表的末端 32 b.extend([1, 2, 3]) 33 c.append([1, 2, 3]) 34 35 # b = [9,8] 36 # 结果: [9, 8, 1, 2, 3] 37 print(b) 38 39 # c = [1,2,3,4] 40 # 结果: [1, 2, 3, 4, [1, 2, 3]] 41 print(c)
实现可切片的对象
模式[start:end:step]
- start: 表示切片的开始位置,默认为0
- end : 表示切片截止(但不包含)位置,默认为列表的长度
- step : 表示切片的步长,默认为1
- 当start为0时可省略
- 当end为列表长度时可省略
- 当step为1时可省略,并且省略步长时可以同时省略最后一个冒号.
- 注意: 当step为负整数时,表示反向切片,这时start值要比end值大才行.
- 所有切片取值的操作会返回一个新的列表
通过示例代码来体会切片的强大之处
- a_list = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
- 列表取值的操作
- a_list[::] 返回包含原列表中所有元素的新列表
- a_list[::-1] 返回包含原列表中所有元素的逆序列表
- a_list[::2] 隔一个取一个,获取偶数位置的元素
- a_list[1::2] 隔一个取一个,获取奇数位置的元素
- a_list[3:6] 指定切片的开始和结束的位置
- a_list[0:100] 切片结束位置大于列表长度时,从列表尾部截断
- a_list[100:] 切片开始位置大于列表长度时,返回空列表
- 列表修改(赋值)操作
- a_list[len(a_list):] = [9] 在列表尾部增加元素
- a_list[:0] = [1, 2] 在列表头部插入元素
- a_list[3:3] = [88] 在列表中间指定位置插入元素
- a_list[:3] = [1, 2] 替换列表元素,等号两边的列表长度相等
- a_list[3:] = [4, 5, 6] 等号两边的列表长度也可以不相等
- a_list[::2] = [0] * 5 隔一个修改一个
- a_list[::2] = ['a', 'b', 'c', 'd', 'e'] 隔一个修改一个
- a_list[::2] = [1, 2, 3] 左侧切片不连续,等号两边列表长度必须相等,不然会报错 :
ValueError: attempt to assign sequence of size 3 to extended slice of size 5
(尝试将大小为3的序列分配给大小为5的扩展切片) - a_list[:3] = [] 删除列表中前3个元素
- del a_list[:3] 切片元素连续
- del a_list[::2] 切片元素不连续,隔一个删一个
1 a_list = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17] 2 3 # ------------------------------------------------------ 4 # 列表取值的操作 5 6 # 返回包含原列表中所有元素的新列表 7 # 结果: [3, 4, 5, 6, 7, 9, 11, 13, 15, 17] 8 print(a_list[::]) 9 10 # 返回包含原列表中所有元素的逆序列表 11 # 结果: [17, 15, 13, 11, 9, 7, 6, 5, 4, 3] 12 print(a_list[::-1]) 13 14 # 隔一个取一个,获取偶数位置的元素 15 # 结果: [3, 5, 7, 11, 15] 16 print(a_list[::2]) 17 18 # 隔一个取一个,获取奇数位置的元素 19 # 结果: [4, 6, 9, 13, 17] 20 print(a_list[1::2]) 21 22 # 指定切片的开始和结束的位置 23 # 结果: [6, 7, 9] 24 print(a_list[3:6]) 25 26 # 切片结束位置大于列表长度时,从列表尾部截断 27 # 结果: [3, 4, 5, 6, 7, 9, 11, 13, 15, 17] 28 print(a_list[0:100]) 29 30 # 切片开始位置大于列表长度时,返回空列表 31 # 结果: [] 32 print(a_list[100:]) 33 34 # ------------------------------------------------------ 35 # 列表修改(赋值)操作 36 37 # 在列表尾部增加元素 38 a_list[len(a_list):] = [9] 39 # 结果: [3, 4, 5, 6, 7, 9, 11, 13, 15, 17, 9] 40 print(a_list) 41 42 # 在列表头部插入元素 43 a_list[:0] = [1, 2] 44 # 结果: [1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 15, 17] 45 print(a_list) 46 47 # 在列表中间指定位置插入元素 48 a_list[3:3] = [88] 49 # 结果: [3, 4, 5, 88, 6, 7, 9, 11, 13, 15, 17] 50 print(a_list) 51 52 # 替换列表元素,等号两边的列表长度相等 53 a_list[:3] = [1, 2] 54 # 结果: [1, 2, 6, 7, 9, 11, 13, 15, 17] 55 print(a_list) 56 57 # 等号两边的列表长度也可以不相等 58 a_list[3:] = [4, 5, 6] 59 # 结果: [3, 4, 5, 4, 5, 6] 60 print(a_list) 61 62 # 隔一个修改一个 63 a_list[::2] = [0] * 5 64 # 结果: [0, 4, 0, 6, 0, 9, 0, 13, 0, 17] 65 print(a_list) 66 67 # 隔一个修改一个 68 a_list[::2] = ['a', 'b', 'c', 'd', 'e'] 69 # 结果: ['a', 4, 'b', 6, 'c', 9, 'd', 13, 'e', 17] 70 print(a_list) 71 72 # 左侧切片不连续,等号两边列表长度必须相等 73 # 不然会报错 : ValueError: attempt to assign sequence of size 3 to extended slice of size 5 74 # 尝试将大小为3的序列分配给大小为5的扩展切片 75 a_list[::2] = [1, 2, 3] 76 77 # 删除列表中前3个元素 78 a_list[:3] = [] 79 # 结果: [6, 7, 9, 11, 13, 15, 17] 80 print(a_list) 81 82 # 切片元素连续 83 del a_list[:3] 84 # 结果: [6, 7, 9, 11, 13, 15, 17] 85 print(a_list) 86 87 # 切片元素不连续,隔一个删一个 88 del a_list[::2] 89 # 结果: [4, 6, 9, 13, 17] 90 print(a_list)
自定义切片对象
- 魔法函数def __getitem__(self, item)是实现切片的关键.
- 如果一个对象没有实现魔法函数def __getitem__(self, item),对其执行切片的操作,会报错TypeError: 'Group' object is not subscriptable("Group"对象没有下标)
1 """ 2 自定义切片对象 3 4 组的概念(生活中常见的概念) 5 比如学校里的学习小组,公司里的开发组,Django里的用户分组(Django里的Group是管理用户的user) 6 7 需求: 定义一个类Group,希望Group支持切片操作,Group类是不可修改的序列 8 """ 9 10 11 class Group: 12 """ 13 自定义不可变序列,需要实现的魔法函数 14 __reversed__() 15 __getitem__() 16 __len__() 17 __iter__() 18 __contains__() 19 """ 20 21 def __init__(self, group_name, company_name, staffs): 22 self.group_name = group_name 23 self.company_name = company_name 24 self.staffs = staffs 25 26 def __reversed__(self): 27 pass 28 29 def __getitem__(self, item): 30 """ 31 对Group做切片操作,将切片的参数传递给__getitem__()方法中 32 但是有一个问题存在,python的list进行切片操作后还是list对象. 33 而此时对Group做切片操作返回的不是Group对象,而是list. 34 35 所以希望Group进行切片操作后还是一个Group对象,这样的话,就可以不停的对Group对象进行切片操作. 36 """ 37 # sub_group = group[:2] --> group[:2:] --> group[None:2:None] 38 # item = {slice}slice(None, 2, None) 39 return self.staffs[item] 40 41 def __len__(self): 42 pass 43 44 def __iter__(self): 45 pass 46 47 def __contains__(self, item): 48 pass 49 50 51 lang_staffs = ["python", "java", "php", "android"] 52 group = Group("computer", "language", lang_staffs) 53 54 # debug : sub_group = {list}<class 'list'>: ['python', 'java'] 55 sub_group = group[:2] 56 57 # 结果: ['python', 'java'] 对Group对象进行切片操作,返回的结果类型不是Group而是list,这不是我们希望得到的数据类型. 58 print(sub_group)
1 """ 2 自定义切片对象 3 需求: 定义一个类Group,希望Group支持切片操作,Group类是不可修改的序列 4 Group进行进行切片操作后,获取的结果类型还是一个Group类型 5 """ 6 import numbers 7 8 9 class Group: 10 """ 11 自定义不可变序列,需要实现的魔法函数 12 __reversed__() 13 __getitem__() 14 __len__() 15 __iter__() 16 __contains__() 17 """ 18 19 def __init__(self, group_name, company_name, staffs): 20 self.group_name = group_name 21 self.company_name = company_name 22 self.staffs = staffs 23 24 def __reversed__(self): 25 pass 26 27 def __getitem__(self, item): 28 """ 29 希望Group进行切片操作后还是一个Group对象,这样的话,就可以不停的对Group对象进行切片操作. 30 31 当进行切片操作的时候,python解释器会将切片初始化一个slice对象,然后将slice对象传递给__getitem__() 32 魔法函数的item. 33 34 当给序列对象指定索引操作(group[0])时,__getitem__()魔法函数的item将接收一个int类型的值. 35 """ 36 # 获取当前self的class 37 cls = type(self) 38 if isinstance(item, slice): 39 return cls(group_name=self.group_name, company_name=self.company_name, staffs=self.staffs[item]) 40 41 elif isinstance(item, numbers.Integral): 42 43 # self.staffs[item] --> 得到的结果是一个数字 --> 将其变成一个数组[self.staffs[item]] 44 # 因为Group只接收数组,才能不断的做切片操作 45 return cls(group_name=self.group_name, company_name=self.company_name, staffs=[self.staffs[item]]) 46 47 def __len__(self): 48 pass 49 50 def __iter__(self): 51 pass 52 53 def __contains__(self, item): 54 pass 55 56 57 lang_staffs = ["python", "java", "php", "android"] 58 group = Group("computer", "language", lang_staffs) 59 60 # debug: 61 # sub_group = {Group} <__main__.Group object at 0x0000000003657C18> 62 # company_name = {str} 'language' 63 # group_name = {str} 'computer' 64 # staffs = {list} <class 'list'>: ['python', 'java'] 65 sub_group = group[:2] 66 67 # debug: 68 # sub_group1 = {Group} <__main__.Group object at 0x00000000024102B0> 69 # company_name = {str} 'language' 70 # group_name = {str} 'computer' 71 # staffs = {list} <class 'list'>: ['python'] 72 sub_group1 = group[0]
1 """ 2 自定义序列对象 3 需求: 定义一个类Group,Group支持切片操作,Group类是不可修改的序列 4 """ 5 import numbers 6 7 8 class Group: 9 """ 10 自定义不可变序列,需要实现的魔法函数 11 __reversed__() 12 __getitem__() 13 __len__() 14 __iter__() 15 __contains__() 16 """ 17 18 def __init__(self, group_name, company_name, staffs): 19 self.group_name = group_name 20 self.company_name = company_name 21 self.staffs = staffs 22 23 def __reversed__(self): 24 self.staffs.reverse() 25 26 def __getitem__(self, item): 27 cls = type(self) 28 if isinstance(item, slice): 29 return cls(group_name=self.group_name, company_name=self.company_name, staffs=self.staffs[item]) 30 elif isinstance(item, numbers.Integral): 31 return cls(group_name=self.group_name, company_name=self.company_name, staffs=[self.staffs[item]]) 32 33 def __len__(self): 34 # Group的长度委托数组来完成 35 return len(self.staffs) 36 37 def __iter__(self): 38 # 先这样写,后面文章会详细说明 39 return iter(self.staffs) 40 41 def __contains__(self, item): 42 # if...in... 43 if item in self.staffs: 44 return True 45 else: 46 return False 47 48 49 lang_staffs = ["python", "java", "php", "android"] 50 group = Group("computer", "language", lang_staffs) 51 52 53 def do_reversed(): 54 """ 测试反转顺序 """ 55 reversed(group) 56 do_iter() 57 58 59 def do_len(): 60 """ 测试__len__() """ 61 print(len(group)) 62 63 64 def do_contains(): 65 """ 测试__contains__() """ 66 if "python" in group: 67 print("YES") 68 else: 69 print("NO") 70 71 72 def do_iter(): 73 """ 测试__iter__() """ 74 for item in group: 75 print(item) 76 77 78 # 结果: 4 79 do_len() 80 81 # 结果: 82 # python 83 # java 84 # php 85 # android 86 do_iter() 87 88 # 结果: YES 89 do_contains() 90 91 # 结果: 92 # android 93 # php 94 # java 95 # python 96 do_reversed()
bisect模块
- 作用 :
- python中处理已排序的序列的查找模块,用来维护已排序的序列(可修改的序列)
- 排序的顺序是升序
- 始终维护一个已排序的序列
- bisect中的方法都是通过二分查找算法实现的.
- insort()与insort_right()是同一个方法
- 将一个数据插入到以排序的序列中,对序列进行修改.如果插入的数据在序列中已存在,那么插入到已存在数据的最右端
- 如: [1, 2, 2, 3]插入数据2(new) --> [1, 2, 2, 2(new), 3]
- insort_left()
- 将一个数据插入到以排序的序列中,对序列进行修改.如果插入的数据在序列中已存在,那么插入到已存在数据的最左端
- 如: [1, 2, 2, 3]插入数据2(new) --> [1, 2(new), 2, 2, 3]
- bisect()与bisect_right()是同一个方法
- 返回要插入的数据在已排序序列中要插入的索引值,未对序列进行修改.
- 如果插入的数据在序列中已存在,那么将返回插入到已存在数据的最右端的索引值
- 如: [1, 2, 2, 3]插入数据2(new) --> 返回要插入的索引值是3
- bisect_left()
- 返回要插入的数据在已排序序列中要插入的索引值,未对序列进行修改.
- 如果插入的数据在序列中已存在,那么将返回插入到已存在数据的最左端的索引值
- 如: [1, 2, 2, 3]插入数据2(new) --> 返回要插入的索引值是1
1 import bisect 2 3 inter_list = [] 4 bisect.insort(inter_list, 3) 5 bisect.insort(inter_list, 2) 6 bisect.insort(inter_list, 6) 7 bisect.insort(inter_list, 1) 8 bisect.insort(inter_list, 5) 9 bisect.insort(inter_list, 4) 10 11 # 结果: [1, 2, 3, 4, 5, 6] 12 print(inter_list)
1 import bisect 2 3 inter_list = [] 4 bisect.insort(inter_list, 3) 5 bisect.insort(inter_list, 2) 6 bisect.insort(inter_list, 6) 7 bisect.insort(inter_list, 1) 8 bisect.insort(inter_list, 5) 9 bisect.insort(inter_list, 4) 10 11 # 结果: 插入到索引值为2的位置上 12 print(bisect.bisect_left(inter_list, 3)) 13 14 # 结果: 插入到索引值为3的位置上 15 print(bisect.bisect(inter_list, 3)) 16 17 # 结果: [1, 2, 3, 4, 5, 6] 18 # 通过结果证明执行bisect_left()和bisect()这两方法,只是返回需要插入的数据应插入到已排序序列的索引值, 19 # 并没有对已排序的序列进行修改. 20 print(inter_list)
1 import bisect 2 from collections import deque 3 4 inter_list = deque() 5 bisect.insort(inter_list, 'python') 6 bisect.insort(inter_list, 'java') 7 bisect.insort(inter_list, 'php') 8 bisect.insort(inter_list, 'android') 9 bisect.insort(inter_list, 'ios') 10 bisect.insort(inter_list, 'c++') 11 12 # 4 13 print(bisect.bisect_left(inter_list, 'php')) 14 bisect.insort_left(inter_list, 'php') 15 16 # 结果: deque(['android', 'c++', 'ios', 'java', 'php', 'php', 'python']) 17 print(inter_list)
array(数组)模块
- 数组是连续的内存空间,它的性能非常的高
- 在做数据处理或者算法,用array特别多,因为array的效率和性能比list高很多.
- array只能存放指定的数据类型
![]()
- append() ----------- append a new item to the end of the array
- buffer_info() ------ return information giving the current memory info
- byteswap() --------- byteswap all the items of the array
- count() ------------ return number of occurrences of an object
- extend() ----------- extend array by appending multiple elements from an iterable
- fromfile() --------- read items from a file object
- fromlist() --------- append items from the list
- frombytes() -------- append items from the string
- index() ------------ return index of first occurrence of an object
- insert() ----------- insert a new item into the array at a provided position
- pop() -------------- remove and return item (default last)
- remove() ----------- remove first occurrence of an object
- reverse() ---------- reverse the order of the items in the array
- tofile() ----------- write all items to a file object
- tolist() ----------- return the array converted to an ordinary list
- tobytes() ---------- return the array converted to a string
1 import array 2 3 a_list = [11, 22, 33] 4 b_list = [44, 55, 66] 5 6 my_array = array.array("i") 7 8 my_array.append(1) 9 my_array.append(2) 10 my_array.append(4) 11 my_array.append(6) 12 my_array.append(3) 13 my_array.append(6) 14 15 # 结果: array('i', [1, 2, 4, 6, 3, 6]) 16 print(my_array) 17 18 # 结果: (34258736, 6) 19 print(my_array.buffer_info()) 20 21 # 结果: 6在数组中出现的次数 2 22 print(my_array.count(6)) 23 24 # 将序列中的元素逐一添加到数组的后面 25 my_array.extend(a_list) 26 # 结果: array('i', [1, 2, 4, 6, 3, 6, 11, 22, 33]) 27 print(my_array) 28 29 # 将列表中的元素逐一添加到数组的后面 30 my_array.fromlist(b_list) 31 # 结果: array('i', [1, 2, 4, 6, 3, 6, 11, 22, 33, 44, 55, 66]) 32 print(my_array) 33 34 # 将字节转换成机器码 35 my_array.frombytes(bytes(4)) 36 # 结果: array('i', [1, 2, 4, 6, 3, 6, 11, 22, 33, 44, 55, 66, 0]) 37 print(my_array) 38 39 # 报错: ValueError: bytes length not a multiple of item size 40 # 字节长度不是项大小的倍数 41 # my_array.frombytes(bytes(3)) 42 43 # 将第一个匹配的元素的索引值返回 44 index1 = my_array.index(6) 45 # 结果: 3 46 print(index1) 47 48 # 将元素77添加到指定索引的位置上. insert(索引值,元素) 49 my_array.insert(0, 77) 50 # 结果: array('i', [77, 1, 2, 4, 6, 3, 6, 11, 22, 33, 44, 55, 66, 0]) 51 print(my_array) 52 53 # pop()方法默认移除最后一个元素,并将移除的元素返回 54 pop_a = my_array.pop() 55 # 结果: 0 56 print(pop_a) 57 # 结果: array('i', [77, 1, 2, 4, 6, 3, 6, 11, 22, 33, 44, 55, 66]) 58 print(my_array) 59 60 # pop()可以指定要移除元素的索引值,并将移除的元素返回 61 pop_b = my_array.pop(3) 62 # 结果: 4 63 print(pop_b) 64 # 结果: array('i', [77, 1, 2, 6, 3, 6, 11, 22, 33, 44, 55, 66]) 65 print(my_array) 66 67 # remove() 删除第一次匹配的元素,不返回删除的元素. 68 # 如果删除的元素不存在,报错ValueError: array.remove(x): x not in list 69 array_remove = my_array.remove(6) 70 # 结果: None 71 print(array_remove) 72 # 结果: array('i', [77, 1, 2, 3, 6, 11, 22, 33, 44, 55, 66]) 73 print(my_array) 74 75 # 将数组倒序 76 my_array.reverse() 77 # 结果: array('i', [66, 55, 44, 33, 22, 11, 6, 3, 2, 1, 77]) 78 print(my_array) 79 80 # 将数组转化成列表 81 tolist = my_array.tolist() 82 # 结果: [66, 55, 44, 33, 22, 11, 6, 3, 2, 1, 77] 83 print(tolist)
列表推导式,字典推导式,生成器
1 """ 2 列表推导式(列表生成式) 3 通过一行代码来生成列表 4 5 range(n)从零开始,到n-1截止 6 7 列表推导式的出现,可以取代map,reduce,filter函数式编程 8 """ 9 10 # 需求: 提取1~20之间的奇数 11 a_list = [x for x in range(21) if x % 2 == 1] 12 # 结果: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] 13 print(a_list) 14 15 # -------------------------------------------------------------------------------- 16 17 # 使用filter + map 函数式编程,需要两行代码. 18 filter_pattern = filter(lambda x: True if x % 2 == 1 else False, range(21)) 19 map_obj = map(lambda x: x, list(filter_pattern)) 20 # 结果: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] 21 print(list(map_obj))
1 """ 2 字典推导式(字典生成式) 3 通过一行代码来生成字典 4 """ 5 6 # 需求: 将字典的key,value颠倒 7 my_dict = {"python": 22, "java": 24, "php": 8} 8 9 result_dict = {value: key for key, value in my_dict.items()} 10 # {22: 'python', 24: 'java', 8: 'php'} 11 print(result_dict) 12 13 14 15 # 需求将字典的key放到set()集合中 16 key_set = {key for key in my_dict} 17 # 结果: <class 'set'> 18 print(type(key_set)) 19 # 结果: {'php', 'python', 'java'} 20 print(key_set) 21 22 23 24 # 第二种方法,使用字典的内置方法 25 key_set1 = set(my_dict.keys()) 26 # 结果: <class 'set'> 27 print(type(key_set1)) 28 # {'python', 'php', 'java'} 29 print(key_set1)
1 """ 2 推导式变成生成器 3 """ 4 5 # 需求: 从0~20中取出所有的可以被5整除的元素的生成器 6 my_gen = (x for x in range(21) if x % 5 == 0) 7 # 结果: <class 'generator'> 8 print(type(my_gen)) 9 # 结果: [0, 5, 10, 15, 20] 10 print(list(my_gen))
********
posted on 2019-04-06 12:00 jaydenjune 阅读(137) 评论(0) 收藏 举报

浙公网安备 33010602011771号