1_5_列表和列表操作#

作者: ZhouLong
创建日期: 2026 年 01 月 13 日
版本: 1.0

浏览量:

1.列表的基本概念#

列表(List) 是Python中最常用的数据结构之一,它是一个有序、可变的序列,可以存储任意类型的元素。

# 创建列表
empty_list = []                    # 空列表
numbers = [1, 2, 3, 4, 5]          # 整数列表
mixed_list = [1, "hello", 3.14, True]  # 混合类型列表
nested_list = [[1, 2], [3, 4]]     # 嵌套列表

print(type(numbers))  # <class 'list'>

列表中的每个值都有对应的位置值,称之为索引,第一个索引是 0,第二个索引是 1,按顺序以此依此类推。

list4 = ['red', 'green', 'blue', 'yellow', 'white', 'black']
list_indices
list_index_reverse 索引也可以从尾部开始,最后一个元素的索引为 -1,往前一位为 -2,以此类推。
list_index_reverse

2.列表的基本操作#

列表的基础方法是索引访问和切片操作。索引访问是在列表对象后以list[index]进行访问单个元素。切片(slicing)提供了一种简洁高效的方式访问列表的特定部分,基本语法是list[start:stop:step]

  • start:起始索引(闭区间),默认为0。

  • stop:结束索引(开区间),默认为序列长度

  • step:步长(可选),默认为1

注意三个参数在使用时可能会不输入,使用默认值

2.1 访问元素#

fruits = ["apple", "banana", "cherry", "date"]

#一、索引访问
# 正向索引(从0开始)
print(fruits[0])     # "apple"
print(fruits[2])     # "cherry"

# 负向索引(从-1开始)
print(fruits[-1])    # "date"
print(fruits[-2])    # "cherry"

#切片访问
#不填参数,默认输出整个序列
print(fruits[:])     #["apple", "banana", "cherry", "date"]

# 加入范围参数stop,访问多个值
print(fruits[1:3])   # ["banana", "cherry"]
print(fruits[:2])    # ["apple", "banana"]

# 加入范围参数step,访问多个值
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(nums[::2])      # [0, 2, 4, 6, 8] - 每隔一个取一个
print(nums[1::2])     # [1, 3, 5, 7, 9] - 从索引1开始每隔一个

2.2 修改列表#

列表中的元素是可以被修改的,你可以直接替换某个位置的元素,也可以一次替换多个元素。下面通过两个例子来看看如何修改列表。

  • 修改单个元素:通过指定元素的索引(位置编号)来直接赋值,就能将旧元素替换成新元素。注意,索引是从0开始计数的。

  • 修改多个元素(切片修改):通过指定一个索引范围(切片),可以一次替换该范围内的所有元素。新提供的元素列表长度可以和原切片长度不同,这会导致列表总长度发生变化。

fruits = ["apple", "banana", "cherry"]

# 修改单个元素
fruits[1] = "blueberry"
print(fruits)  # ["apple", "blueberry", "cherry"]

# 修改切片
fruits[0:2] = ["apricot", "blackberry"]
print(fruits)  # ["apricot", "blackberry", "cherry"]

2.3 添加元素
#

我们可以使用几种不同的方法来向列表中添加新的元素,它们各有用途:

  • append():在列表的末尾添加一个新元素。这是最常用的添加元素的方法。

  • extend():在列表的末尾添加多个新元素。你可以把它理解为用一个新列表来“扩展”原有的列表。

  • insert():在列表的任意指定位置插入一个新元素。你需要提供两个信息:要插入的索引和要插入的值。

numbers = [1, 2, 3]

# append() - 在末尾添加单个元素
numbers.append(4)
print(numbers)  # [1, 2, 3, 4]

# extend() - 添加多个元素(扩展列表)
numbers.extend([5, 6])
print(numbers)  # [1, 2, 3, 4, 5, 6]

# insert() - 在指定位置插入元素
numbers.insert(2, 99)  # 在索引2处插入99
print(numbers)  # [1, 2, 99, 3, 4, 5, 6]

2.4 删除元素
#

列表中的元素也可以被删除。Python提供了几种方法来删除元素,你可以根据不同的情况来选择:

  • remove():根据元素的值来删除。它会找到列表中第一个与指定值相等的元素,并将其删除。如果列表中有多个相同的值,只有第一个会被删除。

  • pop():根据元素的索引(位置)来删除。它会删除指定位置的元素。如果不指定索引,pop() 会默认删除并返回列表的最后一个元素。

  • clear():一次性删除列表中的所有元素,使其变成一个空列表。

numbers = [1, 2, 3, 4, 5, 6, 3]

# remove() - 删除第一个匹配的元素
numbers.remove(3)
print(numbers)  # [1, 2, 4, 5, 6, 3]

# pop() - 删除并返回指定位置的元素
numbers.pop(1)  # 删除索引1的元素
print(numbers)  # [1, 4, 5, 6, 3]

# clear() - 清空列表
numbers.clear()
print(numbers)  # []

2.5 查找和统计
#

我们可以检查列表中的元素,比如找到某个元素的位置、计算它出现了多少次,或者简单地判断它是否存在。Python为这些常见操作提供了简单的方法:

  • index():在列表中查找某个值,并返回第一个匹配到的元素的索引(位置)。如果值不存在,程序会报错。

  • count():统计某个值在列表中总共出现了几次。

  • in 运算符:这是一个快速检查的简便方法。它用于判断某个值是否存在于列表中,返回一个布尔值(True 表示存在,False 表示不存在)。

fruits = ["apple", "banana", "cherry", "apple", "date"]

# index() - 返回第一个匹配元素的索引
print(fruits.index("banana"))  # 1

# count() - 统计元素出现次数
print(fruits.count("apple"))   # 2

# in 运算符 - 检查元素是否存在
print("cherry" in fruits)      # True
print("grape" in fruits)       # False

2.6 排序和反转
#

我们经常需要对数字列表中的元素进行重新排列,例如按照大小排序或者反转顺序。Python 提供了两种排序方法和一种反转方法:

  • sort():这个方法会直接修改原来的列表,将其中的元素从小到大进行排序(升序)。通过设置参数 reverse=True,可以实现从大到小的降序排序。操作后,原列表的顺序就永久改变了。

  • sorted():这是一个函数,它不会改变原来的列表。它会接收一个列表,然后返回一个全新的、排序好的列表。同样,可以用 reverse=True 参数来降序排序。

  • reverse():这个方法会将列表中元素的顺序完全反转(第一个变最后一个,最后一个变第一个)。它也是直接修改原列表。

numbers = [3, 1, 4, 1, 5, 9, 2]

# sort() - 原地排序(修改原列表)
numbers.sort()
print(numbers)  # [1, 1, 2, 3, 4, 5, 9]

numbers.sort(reverse=True)  # 降序排序
print(numbers)  # [9, 5, 4, 3, 2, 1, 1]

# sorted() - 返回新排序列表(不修改原列表)
original = [3, 1, 4, 1, 5]
sorted_list = sorted(original)
print(f"原列表: {original}, 排序后: {sorted_list}") #原列表: [3, 1, 4, 1, 5], 排序后: [1, 1, 3, 4, 5]

# reverse() - 反转列表
numbers.reverse()
print(numbers)  # [1, 1, 2, 3, 4, 5, 9] 反转后

2.7 列表拼接和重复
#

我们用简单的运算符,将多个列表连接在一起,或者将一个列表重复多次。这是通过 +* 运算符来实现的。

  • 列表拼接 (+):使用加号 + 可以将两个或多个列表顺序连接,生成一个包含所有元素的新列表。此外,2.3中我们介绍过extend()函数也具有此功能。

  • 列表重复 (*):使用乘号 * 可以将一个列表的内容重复指定次数,生成一个更长的、元素重复出现的新列表。这在需要初始化一个具有相同元素的列表时非常有用。

# 列表拼接
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
combined_list = list1 + list2
print(combined_list)  # 输出: [1, 2, 3, 'a', 'b', 'c']

# 列表重复
repeated_list = ['hello'] * 3
print(repeated_list)  # 输出: ['hello', 'hello', 'hello']

numbers = [0] * 5
print(numbers)        # 输出: [0, 0, 0, 0, 0]

# 混合操作
mixed = (list1 * 2) + list2
print(mixed)          # 输出: [1, 2, 3, 1, 2, 3, 'a', 'b', 'c']

3.多维数组的操作
#

建议

多维数组的操作十分重要,后续深度学习的基础就是矩阵运算,像Numpy库和PyTorch都包含了大量的张量和向量运算。

在Python中,我们可以用列表的嵌套(即列表里面包含列表)来表示多维数组,最常见的是二维数组,可以把它想象成一个由行和列组成的“表格”或“矩阵”。对它们的操作,通常需要理解其“行”和“列”的结构。
对于更高维度的数组,其操作原理是相同的,核心在于理解嵌套的层级关系。我们可以把更高维的数组看作是层层嵌套的“容器”。
操作逻辑:无论数组有多少维,你都需要从外向内,逐层使用索引来定位。

  • array[i]: 获取三维数组的第 i 个“层”(即一个二维表格)。

  • array[i][j]: 获取第 i 层的第 j 行(即一个一维列表)。

  • array[i][j][k]: 获取第 i 层、第 j 行、第 k 列的具体元素值。

# 创建二维数组(矩阵)
matrix_2d = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

print("二维数组:")
for row in matrix_2d:
    print(row)

# 访问元素
print(f"\nmatrix_2d[1][2] = {matrix_2d[1][2]}")  # 第2行第3列(索引从0开始)

# 创建三维数组
matrix_3d = [
    [
        [1, 2, 3],
        [4, 5, 6]
    ],
    [
        [7, 8, 9],
        [10, 11, 12]
    ]
]

print(f"\n三维数组形状: {len(matrix_3d)}x{len(matrix_3d[0])}x{len(matrix_3d[0][0])}")
print(f"matrix_3d[1][0][2] = {matrix_3d[1][0][2]}")  # 第2个矩阵的第1行第3列

# 遍历三维数组
print("\n遍历三维数组:")
for i, matrix in enumerate(matrix_3d):
    print(f"矩阵 {i}:")
    for row in matrix:
        print(f"  {row}")

4.列表的复制
#

在复制列表时,有一个重要的概念需要区分:浅复制和深复制。它们之间的区别在于如何处理列表内部的子列表(或其他可变对象)。

  • 浅复制问题:使用 copy() 方法或切片 [:] 进行的是“浅复制”。它只复制了列表的“外层”,如果列表里还有子列表,那么复制的是子列表的引用(可以理解为快捷方式),而不是创建全新的子列表。因此,修改浅复制后的子列表内容,原列表也会跟着改变,因为它们指向的是同一个子列表。

  • 深复制:使用 copy 模块中的 deepcopy() 函数可以进行“深复制”。它会递归地复制列表及其内部所有子对象,创建一个完全独立的新列表。之后修改新列表的任何部分,都不会影响到原列表。

# 浅复制问题
original = [[1, 2], [3, 4]]
shallow_copy = original.copy()  # 或 original[:]

shallow_copy[0][0] = 99
print(f"原列表: {original}")      # [[99, 2], [3, 4]]
print(f"浅复制: {shallow_copy}")  # [[99, 2], [3, 4]]

# 深复制
import copy
deep_copy = copy.deepcopy(original)
deep_copy[0][0] = 100
print(f"原列表: {original}")      # [[99, 2], [3, 4]]
print(f"深复制: {deep_copy}")     # [[100, 2], [3, 4]]

5.列表推导式
#

列表推导式是Python中一种非常简洁、强大的创建列表的方法。它可以用一行代码来代替多行循环,使代码更清晰易读。其基本思想是根据一个已有的序列(如列表、元组、range对象等),通过应用表达式和筛选条件,来生成一个新的列表。

  • 创建新列表:列表推导式的核心是 [表达式 for 变量 in 序列]。它会遍历序列中的每个元素,用“表达式”处理该元素,然后将结果收集到一个新列表中。

  • 添加条件筛选:你可以在推导式末尾添加 if 条件,例如 [表达式 for 变量 in 序列 if 条件]。这样只会将满足条件的元素经过表达式处理后加入新列表。

  • 嵌套循环:列表推导式还可以包含多个 for 子句,用于实现嵌套循环。它按照从左到右的顺序执行循环,可以用来生成组合或创建多维结构。

range() 是 Python 内置函数,用于生成一个整数序列。它非常高效,因为它不会一次性创建所有数字,而是按需生成(惰性计算)。

# range示例
# 生成 3-7 的序列
for i in range(3, 8):
    print(i)  # 输出: 3 4 5 6 7

# 生成 2-10,步长为2
for i in range(2, 11, 2):
    print(i)  # 输出: 2 4 6 8 10

print(list(range(5)))  # [0, 1, 2, 3, 4]   其中list()函数是用于类型转换
# 创建平方数列表
squares = [x**2 for x in range(10)]
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# 带条件的列表推导式
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares)  # [0, 4, 16, 36, 64]

# 嵌套循环的列表推导式
pairs = [(x, y) for x in range(3) for y in range(3)]
print(pairs)  # [(0,0), (0,1), (0,2), (1,0), ...]

6.列表操作的时间复杂度#

操作

时间复杂度

说明

索引访问

O(1)

随机访问快

追加元素

O(1)

平均情况

插入元素

O(n)

需要移动后续元素

删除元素

O(n)

需要移动后续元素

查找元素

O(n)

需要遍历列表

切片

O(k)

k是切片长度