1. 序列类的分类
2.序列的+、+=、extend方法
+与+=的用法区别
代码:
# 常用用法
>>> a = [1, 2]
>>> c = a + [3, 4]
>>> print(c)
[1, 2, 3, 4]
>>> a += [3, 4]
>>> print(a)
[1, 2, 3, 4]
# 区别之处
>>> a += (5, 6)
>>> print(a)
[1, 2, 3, 4, 5, 6]
>>> d = c + (5, 6)
>>> print(c)
Traceback (most recent call last):
File "1_swquence_test.py", line 17, in <module>
d = c + (5, 6)
TypeError: can only concatenate list (not "tuple") to list
上述代码中 我们可以发现,list的 +和+= 后面都可以加list。 可是如果后面接的set, +=也没问题,但+就会报错。+=是通过什么方法实现这样的效果的呢?
- 查看定义 _collections_abc 下的MutableSequence
- MutableSequence中有个魔法函数__iadd__
def __iadd__(self, values):
self.extend(values)
return self
- 再查看extend方法
def extend(self, values):
'S.extend(iterable) -- extend sequence by appending elements from the iterable'
for v in values:
self.append(v)
这个extend传入的values只要是iterable可迭代类型就行,然后这个extend函数会for遍历values一个个地加入self。
extend函数传入的参数只要是可迭代的类型,就可以实现。而+=之所以能把tuple加入list中,本质上就是调用类extend方法
extend与append的区别
一段代码就可以明白
>>> d1 = [1, 2, 3]
>>> d2 = [1, 2, 3]
>>> d1.extend((1, 2, 3))
>>> print(d1)
[1, 2, 3, 1, 2, 3]
>>> d2.append((1, 2, 3))
>>> print(d2)
[1, 2, 3, (1, 2, 3)]
3. 实现可切片对象
切片的用法
代码举例:
# 模式[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] # 切片元素不连续,隔一个删一个
如何自己做一个可以切片的对象?
我们可以模仿 _collections_abc模块中Sequence不可改变的序列, (如果想实现可变序列, 可以模仿MutableSequence)
代码:
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): # reversed(list)会调用该方法
pass
def __getitem__(self, item): # 实现切片
cls = type(self) # 相当于cls=Group() 但软编程可维护性好
if isinstance(item, slice): # sub_group = group[:2]时进入
return cls(group_name=self.group_name, company_name=self.company_name, staffs=self.staffs[item])
elif isinstance(item, numbers.Integral): # g0 = group[0]时进入
return cls(group_name=self.group_name, company_name=self.company_name, staffs=[self.staffs[item]])
def __len__(self):
pass
def __iter__(self):
pass
def __contains__(self, item): # for in 时会调用
pass
staffs = ['cannon1', 'cannon2', 'cannon3', 'cannon4']
group = Group(company_name='company', group_name='user', staffs=staffs)
sub_group = group[:2] # debug时 可以查看内部情况
g0 = group[0]
4. bisect维护排序序列
bisect 可以用来处理已排序的序列
进行排序时, 用二分查找算法,效率高。
代码:
>>> import bisect
>>> inter_list = [] # 只要是可修改的序列类型 如 collections的deque等
>>> bisect.insort(inter_list, 3)
>>> bisect.insort(inter_list, 2)
>>> bisect.insort(inter_list, 5)
>>> bisect.insort(inter_list, 1)
>>> bisect.insort(inter_list, 6)
>>> print(inter_list) # 得到的序列是排序好的,效率高
[1, 2, 3, 5, 6]
>>> print(bisect.bisect(inter_list, 3)) # 用来做查找的 在3后面的位置 就是bisect_right
3
>>> print(bisect.bisect_left(inter_list, 3)) # 用来做查找的 在3前面的位置
2
5. 什么情况下,我们不该使用列表list?
array 等于是c语言的数组
array和list的重要区别:
- array: 只能存放指定的数据类型
- list: 什么都能放,灵活,但效率没array高
>>> import array
>>> my_array = array.array('i') # i表示 signed integer 类型
>>> my_array.append(1)
>>> my_array.append(2)
>>> my_array.append(3)
>>> my_array.append(4)
>>> print(my_array)
array('i', [1, 2, 3, 4])
>>> my_array.append('abc') # 传入的不是指定类型,就会报错
Traceback (most recent call last):
File "5_array.py", line 4, in <module>
my_array = array.array(9)
TypeError: array() argument 1 must be a unicode character, not int
6. 列表推导式、生成器推导式、字典推导式、集合推导式
列表推导式(或称为列表生成式):
# 列表生成式
# 1. 提取1-20中的奇数
# 列表操作, 效率比列表生成式低很多
>>> odd_list1 = []
>>> for i in range(21):
>>> if i % 2 == 1:
>>> odd_list1.append(i)
>>> print(odd_list1)
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
# 换成列表推导式
>>> odd_list2 = [i for i in range(21) if i % 2 == 1]
>>> print(odd_list2)
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
# 2. 复杂逻辑的情况
>>> def hadle_item(item):
>>> return item * item
>>> odd_list3 = [hadle_item(i) for i in range(21) if i % 2 == 1]
>>> print(odd_list3)
[1, 9, 25, 49, 81, 121, 169, 225, 289, 361]
生成器表达式:
# 生成器表达式
>>> odd_gen = (i for i in range(21) if i % 2 ==1)
>>> print(type(odd_gen))
<class 'generator'>
>>> odd_list = list(odd_gen)
>>> print(type(odd_list))
<class 'list'>
>>> print(odd_list)
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
字典推导式:
# 字典推导式
>>> my_dict = {'cannon1':22, 'cannon2':23, 'cannon3':24}
# value变为value^2
>>> reversed_dict = {key:value*value for key, value in my_dict.items()}
>>> print(reversed_dict)
{'cannon1': 484, 'cannon2': 529, 'cannon3': 576}
# key 和 value交换位置
>>> reversed_dict = {value:key for key, value in my_dict.items()}
>>> print(reversed_dict)
{22: 'cannon1', 23: 'cannon2', 24: 'cannon3'}
集合推导式:
# 集合推导式
>>> my_dict = {'cannon1':22, 'cannon2':23, 'cannon3':24}
>>> my_set = {key for key , value in my_dict.items()} # .items()不要忽略
# 取巧法: my_set = set(my_dict.keys()) 但这方法灵活性不够
>>> print(type(my_set))
<class 'set'>
>>> print(my_set) # 得到了想要的集合
{'cannon1', 'cannon2', 'cannon3'}