Python循环中字典存列表重复引用,如何按值传递可变对象?
解决Python中字典可变对象的列表引用问题
这个坑我当初刚学Python的时候也踩过!因为字典是可变对象,你每次往列表里append的其实是它的引用,而不是当前状态的副本,所以最后列表里全指向同一个字典,自然都是最终状态。不过要实现你说的“保存每个迭代的状态快照”,方法有好几种,给你详细说下:
方法1:用字典的copy()方法做浅拷贝
这是最简单的方式,适合字典里没有嵌套可变对象(比如子字典、列表)的情况:
state = {"count": 0} state_list = [] for i in range(3): state["count"] += 1 # 追加当前字典的副本,而不是原字典的引用 state_list.append(state.copy()) print(state_list) # 输出:[{'count': 1}, {'count': 2}, {'count': 3}]
copy()会创建一个新的字典对象,和原字典内容相同,但彼此独立,后续修改原字典不会影响列表里的副本。
方法2:用copy.deepcopy()处理嵌套结构
如果你的state里有嵌套的可变对象(比如字典套列表、子字典),浅拷贝就不够用了——因为浅拷贝只会复制顶层引用,嵌套的可变对象还是共享的。这时候就得用copy模块的deepcopy():
import copy state = {"count": 0, "nested_data": [1]} state_list = [] for i in range(3): state["count"] += 1 state["nested_data"].append(i + 2) # 深度复制,把所有嵌套的可变对象也都复制一遍 state_list.append(copy.deepcopy(state)) print(state_list) # 输出的每个元素都是完全独立的,嵌套列表不会跟着原字典变化
方法3:每次循环新建字典
干脆别在原字典上修改,每次迭代都创建一个全新的字典,从根源上避免引用共享问题:
state_list = [] for i in range(3): # 每次循环都生成新的字典,不存在引用复用 current_state = {"count": i + 1} state_list.append(current_state) print(state_list) # 输出:[{'count': 1}, {'count': 2}, {'count': 3}]
这种方式代码更清爽,尤其适合状态结构简单的场景。
方法4:转成不可变对象(比如元组)
正如你想到的,把字典转成不可变的结构,比如由键值对组成的元组,这样每次存入列表的都是当前状态的“快照”——因为不可变对象不能被修改,自然不会后续被影响:
state = {"count": 0} state_list = [] for i in range(3): state["count"] += 1 # 把字典转成键值对元组的集合,作为快照存入列表 state_snapshot = tuple(state.items()) state_list.append(state_snapshot) print(state_list) # 输出:[(('count', 1),), (('count', 2),), (('count', 3),)] # 后续需要转回字典的话,直接用 dict() 就行:dict(state_list[0])
补充说明
Python里其实没有真正的“按值传递”概念,所有传递都是传递引用。但我们可以通过创建新对象的方式,模拟出“保存当前值”的效果——本质就是让列表里的每个元素都是独立的对象,而不是同一个可变对象的引用。
内容的提问来源于stack exchange,提问作者jsstuball
相关产品推荐
相关产品推荐

