Python 列表和字典常用操作

Python 3.13

列表和字典是 Python 里用得最多的两个容器。这一篇只讲真正高频的操作和几个必须知道的坑。

列表:增删改查

nums = [10, 20, 30]

nums.append(40)          # 末尾追加
nums.insert(0, 5)        # 指定位置插入
nums.remove(20)          # 按值删除(只删第一个)
last = nums.pop()        # 弹出最后一个
print(nums, last)        # [5, 10, 30] 40

按索引删除用 del nums[0];找不到元素时 remove() 会抛 ValueError,不确定是否存在就先判断 if x in nums。

切片

切片语法是 list[start:stop:step],含头不含尾:

nums = [0, 1, 2, 3, 4, 5]
print(nums[1:4])    # [1, 2, 3]
print(nums[:3])     # [0, 1, 2]
print(nums[::2])    # [0, 2, 4]
print(nums[::-1])   # [5, 4, 3, 2, 1, 0] 反转

切片会生成新列表,这是复制列表最简洁的写法:copy = nums[:]。

但要小心嵌套结构——切片是一层浅拷贝,内层列表仍然是共享的:

matrix = [[1, 2], [3, 4]]
shallow = matrix[:]
shallow[0].append(9)
print(matrix)   # [[1, 2, 9], [3, 4]]  原列表也被改了

需要完全独立时用 copy.deepcopy()。

遍历的正确写法

names = ["ann", "bob", "cindy"]

# 需要索引
for i, name in enumerate(names):
    print(i, name)

# 两个列表并行
for name, score in zip(names, [90, 85, 88]):
    print(name, score)

不要在遍历列表的同时增删元素,索引会错位:

# 错误示范
nums = [1, 2, 3, 4]
for n in nums:
    if n % 2 == 0:
        nums.remove(n)
print(nums)   # [1, 3] 侥幸正确,但换成 [1, 2, 2, 3] 就会漏

# 正确写法:生成新列表
nums = [n for n in nums if n % 2 != 0]

字典:取值与遍历

user = {"name": "ann", "age": 30}

user["city"] = "Shenzhen"     # 新增/修改
user.pop("age")               # 删除并返回值

取值有两种风格:

user.get("nickname")            # 不存在返回 None,不报错
user.get("nickname", "匿名")    # 指定默认值
user["nickname"]                # 不存在时抛 KeyError

不确定键是否存在,用 get();确定必须存在,用 [] 让问题尽早暴露。

遍历的三种方式:

for key in user:                    # 遍历键
    print(key)

for key, value in user.items():     # 同时取键值
    print(key, value)

for value in user.values():         # 只取值
    print(value)

字典从 Python 3.7 起保证保持插入顺序,可以放心依赖这个特性。

一个实用组合:分组统计

words = ["apple", "ant", "banana", "berry", "cherry"]
groups = {}

for word in words:
    groups.setdefault(word[0], []).append(word)

print(groups)
# {'a': ['apple', 'ant'], 'b': ['banana', 'berry'], 'c': ['cherry']}

setdefault 在键不存在时先写入默认值,比先判断 if key not in groups 更简洁;Python 3 也常用 collections.defaultdict(list) 做同样的事。

小结

  • 切片是浅拷贝,嵌套结构用 deepcopy。
  • 遍历时不要增删元素,用列表推导式生成新列表。
  • 不确定键存在与否用 get(),确定存在用 []。
  • 字典保序,遍历用 items()。

下一步