
在python中,若在循环外创建列表并在循环内反复修改并追加到另一个列表,会导致所有元素指向同一内存地址,从而出现“每次更新都覆盖全部”的问题。解决方法是在循环内每次创建新列表对象。
在python中,若在循环外创建列表并在循环内反复修改并追加到另一个列表,会导致所有元素指向同一内存地址,从而出现“每次更新都覆盖全部”的问题。解决方法是在循环内每次创建新列表对象。
在强化学习或游戏AI训练数据采集过程中,常需将每轮交互的状态(state)、动作(action)、奖励(reward)等打包为样本,并存入一个二维列表(如 tlistm)中。但如示例代码所示,若复用同一个列表对象 tlistc(即未在循环内重新初始化),则 tlistm[e] = tlistc 实际上是将同一对象的多个引用存入列表——后续对 tlistc 的任何修改(如 tlistc[k] = s[k])都会同步反映在 tlistm 的所有已存元素中,最终导致打印结果中所有行内容完全一致。
✅ 正确做法:在每次循环迭代开始时,新建一个独立的列表对象,确保每个样本互不干扰:
for e in range(episodes):
# ✅ 每次迭代创建全新列表,长度为14(索引0–13)
tlistc = [0] * 14 # 或使用空列表后逐项赋值:tlistc = []
qm = random.randint(0, 5)
env.game(action)
fps.tick(1)
screen.fill(bgcolor)
s = env.get_state()
rew = s[12]
q1 = rew + g * qm
# 填充状态特征(前12维)
for k in range(12):
tlistc[k] = s[k]
tlistc[12] = action # 动作
tlistc[13] = q1 # 目标Q值
# ✅ 直接追加新对象(推荐),而非先append('a')再赋值
tlistm.append(tlistc)
if s[13] == 1:
env.game_reset()
action = random.randint(0, 3)
⚠️ 关键注意事项:
- ❌ 避免 tlistm.append('a'); tlistm[e] = tlistc 这类冗余操作——既增加出错风险,又违背直觉;
- ✅ 使用 tlistm.append(tlistc) 更安全、语义清晰;
- ? 若需深拷贝复杂嵌套结构,可导入 copy.deepcopy(),但本例中纯数值列表用 [0]*14 或 list(s[:12]) + [action, q1] 即可;
- ? 调试建议:在循环末尾添加 print(id(tlistc)),确认每次迭代的 tlistc 内存地址是否不同。
总结:Python 中的列表是可变对象,赋值操作传递的是引用而非副本。构建训练数据时,务必保证每个样本为独立对象——这是数据可靠性与模型训练稳定性的基础前提。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











