Python内置序列一(元组和列表)
Python序列类型
容器序列:
list、tuple、和collections.deque这些序列能存放不同类型的数据。
扁平序列:
str、bytes、bytearray、memoryview和array.array,这些序列只能容纳一种类型。
容器序列存放的是它们所包含的任意类型的对象的引用,而扁平序列里存放的是值而不是引用,换句话说,扁平序列其实是一段连续的内存空间。由此可见扁平序列其实更加紧凑,但是它里面只能存放诸如字符、字节和数值这种基础类型。
可变序列
list、bytearray、array.array、collections.deque和memoryview
不可变序列
tuple、str和bytes
列表推导
示例1:把一个字符串变成unicode码位的列表
示例2
示例2为列表推导的结果,通常的原则是,只用列表推导来创建新的列表,并且尽量保持简短。
元组
元组是不可变列表。
元组拆包
例一:city, year,pop,chg,area=('Tokyo',2003,32450,0.66,8014)
例二:交换两个变量的值:a, b = b, a
例三:>>>t = (20, 8) >>>quotient, remainder = div(*t)
对对象进行切片
我们可以用s[a:b:c]的形式对s在a和b之间以c为间隔取值
对序列使用+和*
python程序员会默认序列是支持+和*的。通常+号两侧的序列由相同类型的数据所构成,在拼接的过程中,两个被操作的序列都不会被修改,python会新建一个包含同类型数据的序列来作为拼接的结果。
如果想要把一个序列复制几份然后再拼接起来,更快捷的做法是把这个序列乘以一个整数。
+和*都遵循这个规律,不修改原有的操作对象,而是构建一个全新的序列。
建立由列表组成的列表
例:一个包含3个列表的列表,嵌套3个列表各自有3个元素来代表井字游戏的一行方块,使用了列表推导
下例展示了另一个方法,这个方法看上去是个诱人的捷径,但实际上是错的
上述这个例子相当于把一个对象追加3次
序列的增量赋值
增量赋值运算符+=和*=的表现取决于它们的第一个操作对象,+=背后的特殊方法是__iadd__,但是如果一个类没有实现这个方法的话,python会退一步调用__add__。
如果a实现了__iadd__方法,就会调用这个方法。同时对可变序列(例如list、bytearray和array.array)来说,a会就地改动,就像调用了a.extend(b)一样。但是如果a没有实现__iadd__的话,a+=b这个表达式的效果就变得跟a=a+b一样了,首先计算a+b,得到一个新的对象,然后赋值给a。也就是说,在这个表达式中,变量名会不会关联到新的对象,完全取决于这个类型有没有实现__iadd__这个方法。
总的来讲,可变序列一般都实现了__iadd__方法,而不可变序列不支持这个操作。
list.sort方法和内置函数sorted
list.sort方法会就地排序列表,也就是说不会把原列表复制一份。这也是这个方法的返回值是None的原因,与list.sort相反的是内置函数sorted,它会新建一个列表作为返回值。这个方法可以接受任何形式的可迭代对象作为参数。
这两个函数的关键字参数:
reverse:如果被设定为True,被排序的序列里的元素会以降序输出。
key:一个只有一个参数的函数,这个函数会被用在序列里的每一个元素上。
当列表不是首选时
虽然列表既灵活又简单,但面对各类需求时,我们可能会有更好的选择。比如,要存放1000万个浮点数的话,数组(array)的效率要高的多,因为数组在背后存放的并不是float对象,而是数字的机器翻译,也就是字节表述。再比如说,如果需要频繁对序列做先进先出的操作,deque的速度会快得多