本文主要内容
序列类型分类:
(1)容器序列、扁平序列
(2)可变序列、不可变序列
列表推导式
生成器表达式
元组拆包
切片
排序(list.sort方法和sorted函数)
bisect
文中代码均放在github上:https://github.com/ampeeg/cnblogs/tree/master/python高级
序列类型分类
所谓序列,即元素有序排列,python标准库用C实现了丰富的序列类型,按照序列中是否可存放不同类型的数据分为"容器序列"和"扁平序列"。
容器序列可以存放统统类型的数据,而扁平序列只能存放一种类型
容器序列:list、tuple、collections.deque
扁平序列:str、bytes、bytearray、memoryview、array.array
按照是否能修改的标准序列又可分为"可变序列"和"不可变序列":
可变序列:list、bytearrary、array.arrary、collections.deque和memoryview
不可变序列:tuple、str和bytes 由于可变序列继承自不可变序列,所以可变序列继承的方法也较多,下面看看它们包含的方法:
方法名 | 不可变序列 | 可变序列 |
__contains__ | 有 | 有 |
__iter__ | 有 | 有 |
__len__ | 有 | 有 |
__getitem__ | 有 | 有 |
__reversed__ | 有 | 有 |
index | 有 | 有 |
count | 有 | 有 |
__setitem__ | 有 | |
__delitem__ | 有 | |
insert | 有 | |
append | 有 | |
reverse | 有 | |
extend | 有 | |
pop | 有 | |
remove | 有 | |
__iadd__ | 有 |
我们以tuple和list类型为例,对比源代码中的方法,可以明显发现list的方法多于tuple:
列表推导式
# 列表推导式生成的是列表,会占用系统内存 |
生成器表达式
# 虽然列表推导式可以用来初始化元组、数组或其他序列类型,但是列表推导式会直接生成列表,占用内存 |
下面我们来对比一下列表推导式和生成器的效率
# 比较列表推导式和生成器 |
元组拆包
# 我们经常这样给两个变量同时赋值 |
################################
#
# 以下的例子用以说明拆包赋值时,解释器会按照__iter__、__getitem__的顺序调用类中的方法
#
################################
class Foo:
def __init__(self, s):
self.s = s def __iter__(self):
print("iter")
return iter(self.s) def __getitem__(self, item):
return self.s[item] if __name__ == "__main__":
foo = Foo("sdfafasfasf")
a, b, *s = foo
print(a, b)
拆包赋值的内部实现
之前我们通过源码已经对比过list和tuple类中的方法和属性,下面列出《流畅的python》整理的列表和元组的方法及属性:
表 列表或元组的方法和属性
列 表 | 元 组 | 说 明 | |
s.__add__(s2)
|
· | · | s1 + s2 , 拼接 |
s.__iadd__(s2) | · | s1 += s2,就地拼接 | |
s.append(e) | · | 在尾部添加一个新元素 | |
s.clear() | · | 删除所有元素 | |
s.__contains__(e) | · | · | s是否包含e |
s.copy() | · | 列表的浅复制 | |
s.count(e) | · | · | e在s中出现的次数 |
s.__delitem__(p) | · | 把位于p的元素删除 | |
s.extend(it) | · | 把可迭代对象it追加给s | |
s.__getitem__(p) | · | · | s[p],获取位置p的元素 |
s.__getnewargs__() | · | 在pickle中支持更加优化的序列化 | |
s.index(e) | · | · | 在s中找到元素e第一次出现的位置 |
x.insert(p,e) | · | 在位置p之前拆入e | |
s.__iter__() | · | · | 获取s的迭代器 |
s.__len__() | · | · | len(s),长度 |
s.__mul__(n) | · | · | s * n,n个s的重复拼接 |
s.__imul__(n) | · | s *= n,就地城府拼接 | |
s.__rmul__(n) | · | · | n * s,反向拼接* |
s.pop([p]) | · | 删除最后或者是位于p的元素,并返回它的值 | |
s.remove(e) | · | 删除s中第一次出现的e | |
s.reverse() | · | 就地把s的元素倒序排列 | |
s.__reversed__() | · | 返回s的倒序迭代器 | |
s.__setitem__(p,e) | · | s[p]=e,把元素e放在位置p,替代已经在那个位置的元素 | |
s.sort([key], [reverse]) | · | 就地对s中的元素进行排序,可选的参数有key和是否倒序reverse |
说明:以上元组中不加黑点的不代表一定不能这样使用,只是其作用和列表不同(说明里面有解释)。例如两个元组a和b进行增量赋值a+=b也是可以的,只是这个操作不是就地拼接,而是生成了新的元组。
切片
''' |
排序(list.sort方法和sorted函数)
''' |
########################## 使自定义类也可使用sorted函数调用 |
bisect
''' |
# 2、关于bisect.insort函数 import bisect |