最近看, 看完了第二章关于序列的内容,感觉补上了一些知识的漏洞,便归纳在此.

序列类型分类

首先,python中的列表类型有很多种,一种常见的分类方法是将它们分为容器序列扁平序列,它们的区别可以由一张表来表示:

容器序列 扁平序列
list,tuple,collections.deque str, bytes, bytearray, memortyview, array.array
能够存放不同类型的数据 只能容纳一种类型
存放的是对象的引用 存放的是值
内存空间可以不连续 连续的内存空间

除了这种分类,还有一种常见的分类,即将他们分为可变序列和不可变序列. 可变序列包括list,bytearray,array.array,collections.deque, memoryview, 不可变序列包括tuple,str,bytes.

列表推导

列表推导是一种常见的使用列表的方式, 常用来构建列表. 虽然它做的事情使用有map,filter组合的lambda表达式也都能做到,但是列表推导在可读性上有着很大的优势,例如:

1
2
3
4
numbers = list(range(10)) # 构建一个0~9的列表  
# 下面分别用列表推导和lambda表达式来筛选出所有奇数并将数字转换成浮点数
odds = [float(i) for i in numbers if i%2] # 列表推导
odds = list(filter(lambda i: i%2, map(float, numbers))) # lambda表达式

当然,我们在使用列表推导生成较大的序列时会占用较大内存,因为此时我们是建立一个完整列表再将其传递出去,使用生成器表达式可以节省内存,因为此时它可以逐个生成元素, 生成器表达式的语法和列表推导基本一致,只要把方括号[]改为圆括号()即可.

元组

提到元组我们一般都将其当做不可变的列表,但是它往往可以当成一种数据记录来加以利用,甚至collections提供的具名元组可以迅速实现一个简单的带属性的类供调试.

1
2
3
4
from collections import namedtuple
City = namedtuple('City', 'name country population') # 声明一个叫City的类,类名为City,含有name,country,population三项属性
beijing = City('Beijing', 'China', '2171') # 声明City的一个实例beijing
print(beijing)
City(name='Beijing', country='China', population='2171')

排序相关

两种常用的排序是list.sortsorted,二者使用同样的排序算法(都使用timesort算法,该算法会自适应地根据数据特点交替使用插入和归并排序,这对来自现实的具有一定数据特点的序列非常有效,但在完全随机的序列排序上不如快速排序), 其主要不同是,list.sort是就地排序,直接改动原列表;而sorted则会将源列表复制一份,返回新的有序列表.

在将数据完成排序后, bisect包中的bisectinsort函数常用来在有序列表中进行查找和插入, 二者都基于二分算法.

列表之外  

通常我们都使用list作为我们的序列类型, 因为它灵活而简单,但是在需求更明确或追求更高效率时,记住我们还有其他更优的选择也不是坏事. 

  1. 数组 常用于我们需要只包含数字的列表时, array.arraylist更高效, 且支持直接从文件读写.
  2. 双向队列 collections.deque常用于需要经常从两端增删元素的场景,它高效而且线程安全,常被用来实现队列和堆栈的操作.
  3. Numpy数组 numpy数组是科学上最常用的科学计算库之一了,常用来处理科学计算,在处理数字时其功能的全面和效率之高都远超python的原生序列.