Z
ZHANK
数据结构

列表 (List)

理解列表创建、索引、切片、增删改查等常用操作

Python 列表 (List)

列表是 Python 中最常用的数据结构。它是有序、可变的集合,用方括号 [] 表示。

学完本章你将掌握: 创建列表、索引切片、增删改查、排序、列表推导式,以及 12+ 个常用方法。


一、创建列表

列表可以存放任意类型的数据,甚至混合类型:

python
# 空列表
empty = []

# 数字列表
numbers = [1, 2, 3, 4, 5]

# 字符串列表
fruits = ["苹果", "香蕉", "橘子"]

# 混合类型(不推荐,但语法允许)
mixed = [1, "hello", True, 3.14, [1, 2]]

# list() 构造函数
chars = list("hello")
print(chars)  # ['h', 'e', 'l', 'l', 'o']

💡 你知道吗list(range(1, 101)) 可以快速生成 1 到 100 的数字列表,比手写快得多。


二、索引——访问元素

列表索引从 0 开始,负数索引从末尾倒数:

python
colors = ["红", "橙", "黄", "绿", "蓝", "靛", "紫"]

print(colors[0])     # 红  — 第一个
print(colors[1])     # 橙
print(colors[3])     # 绿
print(colors[-1])    # 紫  — 最后一个
print(colors[-2])    # 靛  — 倒数第二个
print(colors[-3])    # 蓝

# 索引越界会报错 IndexError
# print(colors[10])  # ❌ IndexError: list index out of range

检查列表是否为空 是常见的需求:

python
items = []
if not items:
    print("列表为空")
if items:
    print("列表有内容")

三、切片——获取子列表

切片语法:list[start:end:step]包含 start,不包含 end

python
nums = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

# 基本切片
print(nums[2:5])     # [20, 30, 40]    索引 2,3,4
print(nums[:4])      # [0, 10, 20, 30]  从头到索引3
print(nums[6:])      # [60, 70, 80, 90] 索引6到末尾
print(nums[:])       # [0,10,20,...,90] 复制整个列表

# 步长
print(nums[::2])     # [0, 20, 40, 60, 80]     每隔一个
print(nums[1::2])    # [10, 30, 50, 70, 90]    从索引1每隔一个
print(nums[::-1])    # [90, 80, ..., 0]        反转列表

# 倒数切片
print(nums[-5:-2])   # [50, 60, 70]  倒数第5到倒数第2
print(nums[-3:])     # [70, 80, 90]  最后3个

💡 你知道吗nums[::-1] 是反转列表的经典写法,但它创建新列表,不修改原列表。要原地反转用 nums.reverse()


四、修改元素

列表是可变的,可以直接通过索引修改:

python
colors = ["红", "绿", "蓝"]

# 修改单个元素
colors[1] = "黄"
print(colors)  # ['红', '黄', '蓝']

# 批量替换(切片赋值)
colors = ["红", "橙", "黄", "绿", "蓝"]
colors[1:4] = ["粉", "紫"]  # 把索引1~3替换为2个元素
print(colors)  # ['红', '粉', '紫', '蓝']

五、添加元素

三种主要添加方式,各有用途:

python
fruits = ["苹果", "香蕉"]

# append() — 末尾添加一个元素(最常用)
fruits.append("橘子")
print(fruits)  # ['苹果', '香蕉', '橘子']

# insert() — 在指定位置插入
fruits.insert(1, "葡萄")  # 在索引1处插入
print(fruits)  # ['苹果', '葡萄', '香蕉', '橘子']

# extend() — 合并另一个列表
more = ["西瓜", "草莓"]
fruits.extend(more)
print(fruits)  # ['苹果', '葡萄', '香蕉', '橘子', '西瓜', '草莓']

💡 你知道吗extend(list)for x in list: append(x) 快得多,因为 extend 是一次性批量添加。


六、删除元素

多种删除方法,按场景选择:

python
items = ["a", "b", "c", "d", "e", "b"]

# pop() — 删除并返回指定位置元素(默认删除最后一个)
last = items.pop()
print(last)          # b
print(items)         # ['a', 'b', 'c', 'd', 'e']

second = items.pop(1)  # 删除索引1
print(second)        # b
print(items)         # ['a', 'c', 'd', 'e']

# remove() — 按值删除(只删第一个匹配的)
nums = [1, 2, 3, 2, 4]
nums.remove(2)
print(nums)  # [1, 3, 2, 4]  只删了第一个2

# del — 按索引删除(不返回值)
del nums[0]
print(nums)  # [3, 2, 4]
del nums[1:3]  # 删除切片
print(nums)  # [3]

# clear() — 清空整个列表
nums.clear()
print(nums)  # []

💡 常见陷阱remove(2) 如果没有找到元素 2,会抛出 ValueError。不确定是否存在时先判断 if 2 in nums: nums.remove(2)


七、查——查找与统计

python
fruits = ["苹果", "香蕉", "橘子", "香蕉", "葡萄"]

# len() — 列表长度
print(len(fruits))       # 5

# count() — 统计出现次数
print(fruits.count("香蕉"))  # 2
print(fruits.count("西瓜"))  # 0(不存在返回0,不会报错)

# index() — 查找第一个匹配的索引
print(fruits.index("橘子"))  # 2
print(fruits.index("香蕉"))  # 1(只返回第一个)

# in — 成员检查
print("苹果" in fruits)     # True
print("西瓜" in fruits)     # False
print("西瓜" not in fruits) # True

💡 性能提示in 对列表是 O(n) 查找,元素多时较慢。如果需要频繁做成员检查,使用后面的集合 (Set) 会更高效。


八、排序

python
nums = [3, 1, 4, 1, 5, 9, 2, 6]

# sorted() — 返回新列表,不修改原列表
asc = sorted(nums)
desc = sorted(nums, reverse=True)
print(asc)   # [1, 1, 2, 3, 4, 5, 6, 9]
print(desc)  # [9, 6, 5, 4, 3, 2, 1, 1]

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

# 字符串排序
words = ["banana", "Apple", "cherry", "apple"]
words.sort()                     # 默认:大写优先
print(words)  # ['Apple', 'apple', 'banana', 'cherry']

words.sort(key=str.lower)        # 不区分大小写
print(words)  # ['Apple', 'apple', 'banana', 'cherry']

按自定义规则排序——这是一个非常有用的技巧:

python
# 按字符串长度排序
words = ["python", "go", "c", "javascript", "rust"]
words.sort(key=len)
print(words)  # ['c', 'go', 'rust', 'python', 'javascript']

# 按元组中第二个元素排序(回顾上一章的元组知识)
students = [("小明", 85), ("小红", 92), ("小刚", 78)]
students.sort(key=lambda s: s[1])  # 按分数排序
print(students)  # [('小刚', 78), ('小明', 85), ('小红', 92)]

九、复制列表

这是一个初学者 最常见的陷阱

python
a = [1, 2, 3]

# ❌ 错误方式:这不是复制,是指向同一个列表!
b = a
b[0] = 999
print(a)  # [999, 2, 3] — a 也被改了!

# ✅ 正确复制方式
a = [1, 2, 3]
b = a.copy()           # 方法1:copy()
c = list(a)            # 方法2:构造函数
d = a[:]               # 方法3:切片
e = a + []             # 方法4:拼接空列表

b[0] = 999
print(a)  # [1, 2, 3] — 原列表不受影响
print(b)  # [999, 2, 3]

⚠️ 注意:以上都是浅拷贝。如果列表中包含嵌套列表,内部列表仍然共享:

python
nested = [[1, 2], [3, 4]]
shallow = nested.copy()
shallow[0][0] = 999
print(nested[0])  # [999, 2] — 内部列表被修改了!

# 深拷贝需要 import copy
import copy
deep = copy.deepcopy(nested)
deep[0][0] = 1
print(nested[0])  # [999, 2] — 原列表不受影响

十、列表推导式

一行代码代替多行循环,Python 最优雅的特性之一:

python
# 基本形式
squares = [x**2 for x in range(1, 6)]
print(squares)  # [1, 4, 9, 16, 25]

# 带条件的推导式
evens = [x for x in range(20) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# 多层循环(了解即可)
pairs = [(x, y) for x in range(2) for y in range(3)]
print(pairs)  # [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2)]

# 嵌套 if-else(三元表达式在推导式中)
labels = ["偶数" if x % 2 == 0 else "奇数" for x in range(1, 6)]
print(labels)  # ['奇数', '偶数', '奇数', '偶数', '奇数']

💡 性能提示:列表推导式比等价的 for + append 快约 2-3 倍,代码也更简洁。


十一、遍历技巧

python
fruits = ["苹果", "香蕉", "橘子"]

# 方式1:直接遍历元素(最常用)
for fruit in fruits:
    print(fruit)

# 方式2:需要索引时用 enumerate()
for i, fruit in enumerate(fruits):
    print(f"{i}: {fruit}")

# 方式3:同时遍历多个列表用 zip()
names = ["小明", "小红", "小刚"]
scores = [85, 92, 78]
for name, score in zip(names, scores):
    print(f"{name}: {score}分")

# 方式4:反向遍历
for fruit in reversed(fruits):
    print(fruit)

十二、常用方法速查表

方法用途是否修改原列表
`append(x)`末尾添加元素
`extend(iter)`合并列表
`insert(i, x)`在位置 i 插入
`remove(x)`删除第一个 x
`pop(i)`删除位置 i 并返回
`clear()`清空
`index(x)`查找 x 的位置
`count(x)`统计 x 出现次数
`sort()`原地排序
`reverse()`原地反转
`copy()`浅拷贝

小结

  1. 列表用 [] 创建,元素有序可重复,支持索引和切片
  2. append 加末尾,insert 插指定位置,extend 合并列表
  3. pop 删索引,remove 删值,clear 清空,del 删索引或切片
  4. a = b 不是复制,用 copy()a[:]
  5. 列表推导式让代码简洁高效,值得多用
  6. 排序用 sort()sorted(),结合 key 参数可以自定义规则

小练习

  1. 创建一个包含数字 1 到 10 的列表,然后反转
  2. 从列表 [3, 7, 1, 9, 2, 5] 中找出最大值和最小值
  3. 列表推导式生成 1 到 100 中所有能被 7 整除的数
  4. 把列表 ["a", "b", "c"][1, 2, 3] 组合成 ["a1", "b2", "c3"]

💬 下一章预告:学完列表后,下一章学习元组 (Tuple)——它和列表很像,但最大的区别是不可修改,这在某些场景下非常有用。