自定义序列
序列是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}
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}
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}
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 # 结果:
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 # 结果:
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 # 结果:
8 print(type(my_gen))
9 # 结果: [0, 5, 10, 15, 20]
10 print(list(my_gen))
********