名字绑定对象

Python 变量名绑定到对象。赋值不自动复制对象,两个名字可能引用同一个列表;函数参数也遵循同样的绑定方式。对象是否可变,比“参数是不是按值传递”更有解释力。

a = [1, 2]
b = a
b.append(3)
assert a == [1, 2, 3]
c = a.copy()
c.append(4)
assert a == [1, 2, 3]

浅复制只复制外层容器。嵌套列表的内层对象仍可能共享,构造二维数组时应使用 [[0 for _ in range(cols)] for _ in range(rows)],而不是重复引用同一行。

按用途选容器

列表适合按位置访问和尾部追加;字典保存键到值的映射;集合用于去重和成员判断;元组可以表达固定结构。字典与集合的键需要可哈希,普通列表不能直接作为键。需要从两端进出的队列时使用 collections.deque,避免反复在列表头部移除元素。

from collections import Counter, deque

counts = Counter("banana")
queue = deque(["start"])
queue.append("next")
assert queue.popleft() == "start"
assert counts["a"] == 3

函数与边界

默认参数在函数定义时求值。可变默认列表会被多次调用共享,因此需要每次创建新容器时,用 None 作为默认值并在函数内初始化。异常表达失败,调用方必须知道哪些异常属于输入问题,哪些意味着外部资源不可用。

算法中还要注意整数除法 // 与 /、切片产生的复制成本、递归深度和浮点比较。任意精度整数不会固定宽度溢出,但位数增长仍有时间和空间成本。

练习与面试自查

写一个词频统计函数,并测试空输入、大小写和重复词。构造浅复制不能隔离修改的嵌套列表示例。解释 a == b 比较值而 a is b 比较对象身份,以及为什么不能凭几次运行结果依赖整数或字符串的身份复用。

参考资料