列表
序列是 Python 中最基本的数据结构,序列中每一个元素都会被分配一个用于表示其位置的数字,即索引。序列的索引从 0 开始。Python 中有 6 个序列类型,常用的是列表和元组。所有序列类型都可以进行索引、切片、加、乘和成员检查的操作。
列表是最常用的数据类型,通常使用在方括号中使用逗号分割值的形式定义,列表的数据项不需要有相同的数据类型。空列表可以使用[]
,或者list()
函数来创建。
list1 = ['a', 'b', 'c']
list2 = [1, 2, 3, 4, 5]
list3 = ['a', 'b', 'c', 1, 2, 3]
list4 = list()
list5 = []
列表使用索引来访问相应的元素,并且可以对元素进行修改。要删除列表元素需要使用del
语句。例如:
list1 = [1, 2, 3, 4, 5]
print(list1[2]) # 输出 3
list1[2] = 9
print(list1) # 输出[1, 2, 9, 4, 5]
del list1[3]
print(list1) # 输出[1, 2, 9, 5]
在使用索引访问列表元素时需注意超范围访问,即下标越界,此时 Python 会抛出IndexError
。列表可以嵌套来定义多维列表,例如:[[1, 2, 3], ['a', 'b', 'c']]
。
列表操作
使用+
可以拼接组合两个列表,*
可以将列表的内容重复指定次数,in
可以用来判断元素是否存在于列表中,搭配for
可以用来进行列表内容的迭代。
使用for
来进行列表迭代的时候,默认是直接迭代列表中的值,如果需要获取元素的索引,则需要使用enumerate()
函数来辅助,该函数是一个生成器,每次会返回一个元组,其中第一个元素为索引值,第二个元素为索引对应的值,使用格式一般为for index, element in enumerate(list)
。
对于列表,Python 提供了以下函数和方法。
len(list)
,返回列表元素个数。max(list)
,返回列表中元素的最大值。min(list)
,返回列表中元素最小值。list(tuple)
,将元组转换为列表。list.append(obj)
,将obj
添加到列表末尾。list.count(obj)
,统计列表中obj
出现的次数。list.extend(seq)
,在列表末尾追加另一个列表中的元素。list.index(obj)
,返回obj
在列表中的索引。list.insert(index, obj)
,将obj
插入到列表的指定索引位置。list.pop(index=-1)
,移除列表中指定索引的元素,默认最后一个元素,并返回其值。list.remove(obj)
,移除列表中obj
的第一个匹配项。list.reverse()
,返回反转后的列表。list.sort(cmp=None, key=None, reverse=False)
,对原列表进行排序。list.clear()
,清空列表。list.copy()
,复制列表。
切片
切片是 Python 中强大功能之一,常用于操作序列和字符串。切片与序列和字符串的索引访问类似,都是使用方括号,但格式不同。切片可以包含三个数字,完整格式为:[起始索引:结束索引:步进]
。这三个数字可正可负,分别表示不同的含义。切片中的这三个数字有些时候可以省略,但起始索引和结束索引之间的冒号不可以省略。
列表与字符串中每个元素都对应一正一负两个索引值,其中正值索引是从左向右的索引,负值索引是从右向左的索引。所以切片中步进值为正表示从左向右截取,负值则表示从右向左截取。
切片应用于列表,其返回结果也还是列表;应用于字符串,其返回结果依旧是字符串。
以下通过一些示例,来说明不同切片值的含义。假设有一个列表a = [1, 2, 3, 4, 5, 6, 7]
,就可以有以下操作。
a[:]
,返回完整列表内容。a[4:]
,返回索引从 4 开始以后的全部数据,即[5, 6, 7]
。a[:3]
,返回索引$[0,3)$的元素组成的集合,即[1, 2, 3]
。a[:-5]
,返回 0 到从右数第五个元素,即[1, 2]
。a[:5:2]
,以步进 2 返回 0 到 5 的元素,即返回索引 0、2、4,即[1, 3, 5]
。a[:4:-1]
,步进为负值,从右侧开始取到索引 4 的前一个元素位置,即[7, 6]
。a[:10]
,返回索引$[0, 10)$的的全部数据,超过实际索引后也不会报错。a[::-1]
,返回逆序列表,即[7, 6, 5, 4, 3, 2, 1]
。
任何情况下都需要记住,结束索引始终不会包含在切片中。对切片进行操作,会改变列表的结构和值。下面通过几个示例来演示对切片赋值的操作结果。
list = ['a', 'b', 'c', 'd', 'e', 'f']
list[len(list):] = ['g', 'h'] # 将指定列表添加到原列表的末尾,操作完后的 list 是['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
list[1:4] = [1, 2] # 用指定列表替换原列表中切片部分,操作完成后的 list 是['a', 1, 2, 'e', 'f', 'g', 'h']
list[:] = '' # 替换掉原列表的内容,而不是创建一个新的对象
列表推导式
列表推导式提供了创建列表的简单途径,通常用于将一些操作应用于序列的每个元素,用其获得的结果作为生成新列表的元素,或者根据确定的条件创建子序列。用简单的话说,列表推导式相当于 Java 语言中 stream 操作的map
和filter
的组合。列表推导式都在for
关键字后跟一个表达式,之后还会跟零到多个for
或者if
子句;返回结果是一个根据表达式从其后的 for
和 if
上下文环境中生成出来的列表。如果希望返回元组,则需要用括号包裹推导式。
下面看一些示例。
vec = [2, 4, 6]
list = [3*x for x in vec]
print(list) # 会输出[6, 12, 18]
list = [[x, x**2] for x in vec]
print(list) # 会输出[[2, 4], [4, 16], [6, 36]]
list = [3*x for x in vec if x > 3]
print(list) # 会输出[12, 18]
列表推导式中可以使用复杂表达式和嵌套函数。下面给出一些技巧性的演示,读者可以自行在解析器中尝试运行。
vec1 = [2, 4, 6]
vec2 = [4, 3, -9]
print([x*y for x in vec1 for y in vec2])
print([vec1[i]\*vec2[i] for i in range(len(vec1))])
print([str(round(355/113, i) for i in range(1, 6))])
例如有以下矩阵:
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
]
可以使用以下推导式完成矩阵的旋转:
new_matrix = [[row[i] for row in matrix] for i in range(4)]