《Think Python 2e》学习精粹(十):列表
文章目录
- 列表(list):是由多个值组成的序列,Python中最有用的内置类型之一;
- 元素(element):列表中的值,也称为 项(item);
1、列表是一个序列
- 在列表中,值可以是任何数据类型,同一也不需要是相同的数据类型,一个不包含元素的列表被称为空列表;
- 创建新列表的方法最简单的是用方括号( [ 和 ] )将元素包括起来;
[10, 20, 30, 40]
- 一个列表在另一个列表中,称为嵌套(nested)列表;
- 可以将列表作为值赋给变量;
>>> a = [1, 2, 3, 4]
>>> print(a)
[1, 2, 3, 4]
2、列表是可变的
- 访问列表中元素的语法:
- 是通过方括号运算符实现的;
- 括号中的表达式指定了元素的索引;
- 索引从0开始;
>>> cheeses = ['Cheddar', 'Edam', 'Gouda']
>>> cheeses[0]
'Cheddar'
- 列表是可变的,当括号运算符出现在赋值语句的左边时,它就指向了列表中将被赋值的元素;
>>> numbers = [42, 123]
>>> numbers[1] = 5
>>> numbers = [42, 5]
-
列表下标的工作原理:
- 任何整数表达式都可以用作下标;
- 读或写一个不存在的元素,将会得到一个索引错误(IndexError);
- 如果下标是负数,它将从列表的末端开始访问列表;
-
in 运算符在列表中同样可以使用,运算结果当然也是 True 或者 False;
3、遍历列表
- for 循环,用 in 访问列表项,与字符串遍历相同;
for cheese in cheeses:
print(cheese)
- for 循环,结合内置函数 range 和 len 通过下标访问列表项;
for i in range(len(numbers)):
numbers[i] = numbers[i] * 2
- 对一个空列表执行for循环时,将不会执行循环的主体;
for x in []:
print('This never happens.')
- 嵌套的列表本身还是被看作一个单个元素;
4、列表操作
- 运算符 + 拼接多个列表;
>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
- 运算符 * 以给定次数的重复一个列表
>>> [1, 2, 3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
5、列表切片
- 切片(slice)运算符同样适用于对列表;
>>> t = ['a', 'b', 'c', 'd', 'e', 'f']
>>> t[1:3]
['b', 'c']
- 由于列表是可变的,通常在修改列表之前,对列表进行拷贝是很有用的;
- 切片运算符放在赋值语句的左边时,可以一次更新多个元素;
>>> t = ['a', 'b', 'c', 'd', 'e', 'f']
>>> t[1:3] = ['x', 'y']
>>> t
['a', 'x', 'y', 'd', 'e', 'f']
6、列表方法
- append 方法添加一个新元素到列表的末端;
>>> t = ['a', 'b', 'c']
>>> t.append('d')
>>> t
['a', 'b', 'c', 'd']
- extend 方法将接受一个列表作为参数,并将其中的所有元素添加至目标列表中;
>>> t1 = ['a', 'b', 'c']
>>> t2 = ['d', 'e']
>>> t1.extend(t2)
>>> t1
['a', 'b', 'c', 'd', 'e']
- sort 方法将列表中的元素从小到大进行排序;
>>> t = ['d', 'c', 'e', 'b', 'a']
>>> t.sort()
>>> t
['a', 'b', 'c', 'd', 'e']
- 大部分的列表方法都是无返回值的,它们对列表进行修改,然后返回None;
>>> a = [4, 3, 2, 1]
>>> a.sort()
>>> print(a)
[1, 2, 3, 4]
>>> b = a.sort()
>>> print(b)
None
7、映射、筛选和归并
- 增量赋值语句(augmented assignment statement):用运算符 += 更新变量的赋值语句,运算符左边是待更新的变量,运算符右边是增量,例如
total += x
;
- Python的一个内建内置函数 sum 执行把一个列表中的元素加起来的操作;
- 将一系列的元素合并成一个单一值的操作称为 归并(reduce);
- 字符串方法 capitalize 返回一个首字母大写的字符串;
>>> a = 'abc def ghk'
>>> print(a.capitalize())
Abc def ghk
- 映射一个函数(例如字符串方法 capitalize )到序列中的每个元素上, 这样的操作被称为 映射(map);
- 从列表中选择一些元素,并返回一个子列表,这样的操作被称为 筛选(filter);
8、删除元素
- 删除元素方法之一:使用方法 pop,接受待删除元素下标(索引)删除并返回该元素,如果不提供下标,将删除并返回最后一个元素;
>>> t = ['a', 'b', 'c']
>>> x = t.pop(1)
>>> t
['a', 'c']
>>> x
'b'
- 删除元素方法之二:使用 del 运算符;
>>> t = ['a', 'b', 'c']
>>> del t[1]
>>> t
['a', 'c']
- 删除元素方法之二:如果知道要删除的值(但是不知道其下标),可以使用方法 remove,remove 的返回值是 None;
>>> t = ['a', 'b', 'c']
>>> t.remove('b')
>>> t
['a', 'c']
- 要移除多个元素,你可以结合切片索引使用 del;
>>> t = ['a', 'b', 'c', 'd', 'e', 'f']
>>> del t[1:5]
>>> t
['a', 'f']
9、列表和字符串
- 函数 list 将一个字符串转换为字符的列表;
>>> s = 'spam'
>>> t = list(s)
>>> t
['s', 'p', 'a', 'm']
- 字符串方法 split 将一个字符串分割成单词并返回字符串列表;
>>> s = 'pining for the fjords'
>>> t = s.split()
>>> t
['pining', 'for', 'the', 'fjords']
- 字符串方法 split 可以提供一个叫做 分隔符(delimiter) 的可选参数,指定什么字符作为单词之间的分界线;
- 字符串方法 join 的功能和 split 相反;
>>> t = ['pining', 'for', 'the', 'fjords']
>>> delimiter = ' '
>>> s = delimiter.join(t)
>>> s
'pining for the fjords'
10、对象和值
- 两个对象相同,它们的值也是相等的,但是如果它们的值是相等的,它们不一定是相同的;
- 用赋值语句给不同变量赋值相等的列表,在 Python 中生成不同的对象;
>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a == b
True
>>> a is b
False
>>> a = b
>>> a is b
True
- 用赋值语句给不同变量赋值等的字符串,在 Python 中生成同一个对象;
>>> a = b
>>> a is b
True
>>> a = 'banana'
>>> b = 'banana'
>>> a == b
True
>>> a is b
True
11、别名
- 变量和对象之间的关联称为 引用(reference) ;
- 如果一个对象有多于一个引用,那它也会有多个名称,我们称这个对象是 有别名的(aliased);
- 如果一个有别名的对象是可变的,对其中一个别名(alias)的改变将影响到其它的别名;
- 尽管这个行为很有用,但是容易导致出现错误,通常避免对于可变对象例如列表使用别名相对更安全,对于像字符串这样的不可变对象,使用别名没有什么问题;
12、列表参数
- 将一个列表作为参数传给一个函数,函数将得到这个列表的一个引用,如果函数对这个列表进行了修改,会在调用者中有所体现
- 需要注意的是修改列表操作和创建列表操作间的区别,例如,append 方法是修改一个列表,而 + 运算符是创建一个新的列表,编写一个修改列表的函数,这一点就很重要;
>>> def bad_delete_head(t):
>>> t = t[1:]
>>>
>>> t4 = [1, 2, 3]
>>> bad_delete_head(t4)
>>> t4
[1, 2, 3]
12、调试
- 粗心地使用列表等可变对象会导致长时间的调试,下面列举一些常见的陷阱以及避免它们的方法:
- 在使用 list 方法和操作符之前,应该仔细阅读文档,然后在交互模式下测试:大多数的列表方法会对参数进行修改,然后返回 None ,这和字符串方法相反,后者保留原始的字符串并返回一个新的字符串;
- 选择一种写法,坚持下去:列表的一个问题就是有太多方法可以做同样的事情,在交互模式下尝试每一个例子,保证明白它们做了什么 注意只有最后一个会导致运行时错误,其他的都是合乎规范的的,但结果却是错的;
- 通过创建拷贝来避免别名:下面 t1 就是 t 的别名,而拷贝而来的 t2 和 t 并不指向同一对象,就不是 t 的别名;
>>> t = [3, 1, 2] >>> t1 = t >>> t1 is t True >>> t2 = t[:] >>> t2 is t False