
python 字典是可变对象,赋值操作(如 `a = b`)仅复制引用而非数据本身;只有重新绑定变量(如 `d = {}`)才会切断原有引用,而原地修改(如 `d[key] = val`)则会同步影响所有指向该字典的变量。
在 Python 中,理解“赋值即引用”是避免意外数据共享的关键。当你执行 dictionary1 = dictionary2,实际发生的是 dictionary1 和 dictionary2 共同指向内存中同一个字典对象——它们不是两个独立副本,而是同一本字典的两个“书签”。
这解释了你观察到的第一个代码片段的问题:
set1 = {} # ✅ 创建一个空字典对象,set1 指向它
for i in s1:
for j in range(1, len(i)):
set1[i[j][0]] = i[j][1] # ⚠️ 原地修改:向同一个字典添加/更新键值对
set2[i[0]] = set1 # ⚠️ 赋值引用:set2[i[0]] 指向 set1 当前所指的同一对象由于 set1 = {} 只在循环外执行一次,整个循环中 set1 始终引用同一个字典对象。每次 set2[i[0]] = set1 都只是把该对象的引用存入 set2 的不同键下。最终 set2 的所有值都指向同一个字典——最后一次循环写入的内容覆盖了之前所有修改,导致所有键对应相同的最终状态。
而第二个版本正确解决了这个问题:
立即学习“Python免费学习笔记(深入)”;
for i in s1:
set1 = {} # ✅ 每次迭代都创建一个全新的字典对象
for j in range(1, len(i)):
set1[i[j][0]] = i[j][1] # ✅ 修改的是本次新建的独立字典
set2[i[0]] = set1 # ✅ 存入的是这个新字典的独立引用此处 set1 = {} 在每次循环开始时执行,意味着为每个 i 分配了一个全新、隔离的字典对象。因此 set2[i[0]] 存储的是彼此无关的引用,最终得到预期结构 {name: {value: pair, ...}, name2: {...}}。
⚠️ 注意:这种引用行为仅适用于可变对象(dict, list, set 等)。对于不可变对象(如 int, str, tuple),赋值后重新绑定变量(如 x = 5; x = 10)不会影响其他变量,因为它们本质上是创建新对象并重定向引用——这正是你第二个例子中 dictionary2 = {1:'f', 2:'g'} 不影响 dictionary1 的原因:dictionary2 已被重新绑定到一个新字典,而 dictionary1 仍牢牢指向原来的那个。
✅ 正确实践建议:
- 若需多个独立副本,请在每次使用前显式创建(如 d = {} 或 d = dict());
- 若需深拷贝嵌套结构,使用 copy.deepcopy();
- 可通过 id(obj) 快速验证两个变量是否指向同一对象(id(a) == id(b) 返回 True 即为同一对象)。
理解引用与对象生命周期,是写出健壮、可预测 Python 代码的基础。










