列表
在本课中,我们将定义列表,介绍它们在 Python 中的使用方式,以及它们与数组的区别!
在 Python 中,列表(list)是一个有序的、包含异质元素的序列。换句话说,列表可以容纳不同数据类型的元素。例如:
1list = ['a', 'apple', 23, 3.14]
初始化列表
1example_list = [3.14159, 'apple', 23] # 创建一个包含元素的列表 2empty_list = [] # 创建一个空列表 3sequence_list = list(range(10)) # 创建一个包含前10个整数的列表 4print(example_list) 5print(empty_list) 6print(sequence_list)
因此,列表可以同时存储整数、字符串、字符、函数以及几乎任何其他数据类型,包括其他列表!请看下面的例子:another_list 包含了两个列表、一个字符串和一个函数!可以通过方括号来访问或“索引”这些元素。使用索引 0 可以访问列表中的第一个元素(如第 7 行所示),使用索引 1 访问第二个元素,依此类推。因此,列表的索引从 0 开始。
1a_list = [2, 'PageFlux', 'A'] 2 3 4def foo(): 5 print('Hello from foo()!') 6 7 8another_list = [a_list, 'Python', foo, ['yet another list']] 9 10print(another_list[0]) # 'aList' 的所有元素 11print(another_list[0][1]) # 'aList' 的第二个元素 12print(another_list[1]) # 'Python' 13print(another_list[3]) # 'yet another list' 14 15# 你也可以调用列表中的函数! 16another_list[2]() # 输出:Hello from foo()!
重要的列表函数
让我们来看一些有用的内置 Python 列表函数。每个操作的时间复杂度均来自 Python Wiki 页面的平均渐近情况。需要注意的是:不要用这些函数来替代面试题的答案。例如,如果被要求对数组/列表进行排序,请不要直接使用 sort() 函数作为答案!
append() 函数
用于将单个元素添加到列表末尾。该函数的时间复杂度为 ,即常数时间。
1list = [1, 3, 5, 'seven'] 2print(list) 3list.append(9) 4print(list)
insert() 函数
将元素插入列表中,使用方式为 list.insert(index, value)。其时间复杂度为 。请自行尝试!
以下代码 list.insert(0,2) 将元素 2 插入到索引为 0 的位置:
1list = [1, 3, 5, 'seven'] 2list.insert(0, 2) 3print(list)
remove() 函数
移除列表中指定的元素,使用方式为 list.remove(element),时间复杂度为 。如果元素不存在,则会抛出运行时错误,如下例所示:
1list = [1, 3, 5, 'seven'] 2print(list) 3list.remove('seven') 4print(list) 5list.remove(0) 6print(list)
pop() 函数
移除指定索引处的元素。若未提供索引,则默认移除最后一个元素。因此 list.pop() 会移除最后一个元素,时间复杂度为 。而 list.pop(2) 会移除索引为 2 的元素(本例中是 5)。此外,弹出第 k 个中间元素所需时间为 ,其中 。
1list = [1, 3, 5, 'seven'] 2print(list) 3list.pop(2) 4print(list)
reverse() 函数
该函数用于反转列表,调用方式为 list.reverse(),时间复杂度为 。
1list = [1, 3, 5, 'seven'] 2print(list) 3list.reverse() 4print(list)
什么是切片(Slicing)?
在大多数编程语言中,访问或修改列表、元组、字符串等对象中的多个元素通常需要使用 for 循环。但在 Python 中,你可以使用方括号和冒号来定义一个范围,从而访问或“切片”列表中的一段元素。
1list[start:end]
其中 start 和 end 分别表示希望访问的列表起始和结束索引。你可以打印这些值、重新初始化它们、对其执行数学运算,以及其他多种操作。我们来看几个例子。
切片语法示例
示例 1:索引列表元素
可以通过索引访问并打印列表元素,如下所示:
1list = list(range(10)) 2print(list) # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 3print(list[0:4]) # 0, 1, 2, 3
注意,不必显式指定起始或结束索引,可以直接留空 start 或 end。
list[start:]表示从 start 开始直到末尾的所有元素
list[:end]表示从开头直到 end(不包含)的所有元素
list[:]表示整个列表的所有元素
进一步示例如下:
1list = list(range(10)) 2print(list[3:]) # 3, 4, 5, 6, 7, 8, 9 3print(list[:3]) # 0, 1, 2 4print(list[:]) # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
示例 2:步长索引
还可以像 for 循环一样按步长索引元素。例如 C++ 中的如下循环:
1for(int i = 0; i < 10; i+=2) 2{ 3 cout << arr[i] << endl; // 打印索引为 i 的数组元素 4}
每次迭代中变量 i 增加 2,并相应地访问数组 arr。在 Python 中,可以用以下简洁语法实现相同功能:
1list[start:stop:step]
其中 step 指定索引的增量,也可以为负数。
例如:
1list = list(range(10)) # 定义一个从0开始的数值范围 2print(list[0:9:2]) # 0, 2, 4, 6, 8 3print(list[9:0:-2]) # 9, 7, 5, 3, 1
第2行:从列表开头开始,每隔一个元素取一个值
第3行:从列表末尾开始,每隔一个元素向前取值
示例 3:初始化列表元素
可以通过指定要更新的元素范围,并将其设置为新值,来添加或修改列表内容:
1arr[start:end] = [new, values, to, insert]
1x = list(range(5)) 2print(x) # 0, 1, 2, 3, 4 3x[1:4] = [45, 21, 83] 4print(x) # 0, 45, 21, 83, 4
方括号中的 1:4 表示将位置 1、2、3(不包括位置 4)的元素替换为新值 [45, 21, 83]。
注意:在 Python 中,range 范围包含起始索引但不包含终止索引本身。因此在此例中,索引为 4 的元素 4 不会被替换。
示例 4:从列表中删除元素
使用 del 关键字可以从列表中删除元素。以下示例删除所有位于偶数索引位置的元素:
1list = list(range(10)) 2print(list) # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 3del list[::2] 4print(list) # 1, 3, 5, 7, 9
第3行 使用了 del 操作。此处省略的起始和结束索引默认为 0 和列表长度,而 2 是步长。
示例 5:负索引
可以使用负数从列表末尾开始反向索引。例如,要访问倒数第五个元素,可使用:
1list[-5]
1list = list(range(10)) 2print(list) 3print(list[4:-1]) # 4, 5, 6, 7, 8
上述示例输出从第 4 个索引到倒数第二个索引之间的元素。
示例 6:字符串中的切片
由于字符串本质上是字符的序列(技术上讲是字符数组),因此也可以对字符串使用切片操作!例如,字符串 "somehow" 可以被拆分为两个子串:
1my_string = "somehow" 2string1 = my_string[:4] 3string2 = my_string[4:] 4print(string1, string2)