Python 列表和字典常用操作
列表和字典是 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()。