第2章主要讲python中序列相关的数据结构
了解序列类型的目的:避免重复造轮子
让自己定义的API跟原生的一样
内置序列类型概览
按存放的数据类型分:容器序列:list/tuple和collections.deque这些,能存放不同类型的数据,存放的对象的引用
扁平序列:str/bytes/bytearray/memoryview/array.array,只能容纳一种类型,存放的是某种类型的值
按能否被修改来分可变序列:list/bytearray, array.array/collections.deque/memoryview
不可变序列:tuple/str/bytes
列表推导和生成器表达式
列表推导
使用列表推导的原则:只用列表推导来创建新的列表,并尽可能简短。
python2中列表推导会有上下文同名变量冲突的问题,python3中没有。
列表推导中for循环的顺序也是由外层到内层。
生成器表达式
用于初始化列表之外的其他类型的序列比较好。
生成器表达式遵守了迭代器协议,逐个产生元素,而不像列表推导那样先建立完整的列表再填内容。
只要把列表推导中的方括号改成圆括号。
元组不仅仅是不可变的列表
元组是对数据的记录,元组的数量和位置信息非常重要。
元组拆包最简单的用法是平行赋值。
可以用号把元组拆包作为函数的参数
python3里加一个变量可以用在平行赋值中
元组可以嵌套使用,如(a,b,(c,d))
具名元组
创建一个具名元组要两个参数:类名和各个字段的名字,字段名可以是一个可迭代对象或者以空格分割的字符串。
具名元组的_fields属性返回一个字段名字的元组
具名元组的_make()方法接收一个可迭代对象来生成实例
具名元组的_asdict()方法返回一个collections.OrderedDict
切片
可以用slice(a,b,c)来定义一个切片对象,list[slice(a,b,c)]等价于list[a:b:c]
python内置的对象都是一维的,只接收单一索引。外部定义的对象,可以接收以逗号分割的多个索引,只要将对象的特殊方法__getitem__定义为以元组接收。a.__getitem__((a,b))
切片可以放在赋值语句的左边,或者作为del的操作对象,就可以对序列进行嫁接,切除,或就地修改。
对序列使用+和*
+和*都不修改原有的操作对象,而是新建一个对象。
用*建立列表的列表的时候要注意,最好用列表推导。
序列的增量赋值
对象使用+=的时候,如果对象实现了__iadd__(),会就地加,没有的话,会调用__add__()创建一个新的对象,再赋值过去。
list.sort方法和内置函数sorted
list.sort()方法就地排序,不返回新的对象,返回的是None。
如果不返回新的对象就返回None,是python中函数的一个惯用写法。
内置方法sorted会返回新的对象。
list.sort和sorted都接收两个可选参数,reverse和key。
reverse=True的时候降序。
key接收的是用在每一个元素上的函数,如key=len。注意,是函数名,所以不带括号。
用bisect来管理已排序的序列
这个模块专门用一节来讲,是不是很牛逼啊?但是从来没用过。
bisect模块主要包括两个函数,bisect, insort。
bisect用二分查找从有序序列中查到要找的值,返回index。
insort讲值插入有序序列中。
当列表不是首选时
数组 array.array
专门处理数据,会很快,很方便。
内存视图memoryview
类型转换方便,省内存。
numpy和Scipy
双向队列和其他队列