容器序列
list、tuple 和 collections.deque 这些序列能存放不同类型的
数据。
扁平序列
int、str、bytes、bytearray、memoryview 和 array.array,这类
序列只能容纳一种类型。
可变序列
list、bytearray、array.array、collections.deque 和
memoryview。
不可变序列
int、tuple、str 和 bytes。
2.2.1 列表推导和可读性
字典推导式:
2.2.2 列表推导同filter和map的比较
2.3.2 元组拆包
定义变量去接收元组内的元素
2.3.4 具名元组
第一个参数为定义的名字,第二个参数为定义的变量(需赋值)
创建一个具名元组需要两个参数,一个是类名,另一个是类的各个字段的名字。后者可以是由数个字符串组成的可迭代对象,或者是由空格分隔开的字段名组成的字符串。
存放在对应字段里的数据要以一串参数的形式传入到构造函数中(注意,元组的构造函数却只接受单一的可迭代对象)
2.4 切片
2.4.1 为什么切片和区间会忽略最后一个元素
当只有最后一个位置信息时,我们也可以快速看出切片和区间里有几个元素:range(3) 和 my_list[:3] 都返回 3 个元素。
当起止位置信息都可见时,我们可以快速计算出切片和区间的长度,用后一个数减去第一个下标(stop - start)即可。
这样做也让我们可以利用任意一个下标来把序列分割成不重叠的两部分,只要写成 my_list[:x] 和 my_list[x:] 就可以了,如下所示。
利用切片进行反转序列以及显示数据
注意点:如果在 a * n 这个语句中,序列 a 里的元素是对其他可变
对象的引用的话,你就需要格外注意了,因为这个式子的结果可能
会出乎意料。比如,你想用 my_list = [[]] * 3 来初始化一个
由列表组成的列表,但是你得到的列表里包含的 3 个元素其实是 3
个引用,而且这 3 个引用指向的都是同一个列表。这可能不是你想
要的效果。
2.6 序列的增量赋值
常见的可变序列__iadd__ 方法实现了就地自增;
对于不可变对象不具有__iadd__方法通过运算获取一个新对象,在将对象赋值给该变量
3.9.3 dict的实现及其导致的结果
01. 键必须是可散列的
支持 hash() 函数,并且通过 __hash__() 方法所得到的散列值是不变的。
支持通过 __eq__() 方法来检测相等性
02. 字典在内存上的开销巨大
由于字典使用了散列表,而散列表又必须是稀疏的,这导致它在空间上的效率低下。
举例而言,如果你需要存放数量巨大的记录,那么放在由元组或是具名元组构成的列表中会是比较好的选择;
用元组取代字典就能节省空间的原因有两个:其一是避免了散列表所耗费的空间,其二是无需把记录中字段的名字在每个元素里都存一遍
03. 键查询很快
dict 的实现是典型的空间换时间:字典类型有着巨大的内存开销,但它们提供了无视数据量大小的快速访问——只要字典能被装在内存里。
3.9.4 set的实现以及导致的结果
集合里的元素必须是可散列的。
集合很消耗内存。
可以很高效地判断元素是否存在于某个集合。元素的次序取决于被添加到集合里的次序。
往集合里添加元素,可能会改变集合里已有元素的次序
可变对象的引用:
可变类型中若把a赋值给b,其实a与b享用同一个内存地址
8.2.1 在==和is之间选择
==是直接判断两个数据的内容是否相同,is是直接判断内存地址是否相同
8.2.2 元组的相对不可变性
元组与多数 Python 集合(列表、字典、集,等等)一样,保存的是对象的引用。1 如果引用的元素是可变的,即便元组本身不可变,元素依然可变。也就是说,元组的不可变性其实是指 tuple 数据结构的物理内容(即保存的引用)不可变,与引用的对象无关。
8.4.1 不要使用可变类型作为参数的默认值
问题在于,没有指定初始乘客的 HauntedBus 实例会共享同一个乘客列表。