我正在尝试更新字典,但是以前的值一直被覆盖。这是我正在使用的代码的简化版本。
selected_session = ""
encounters_to_add = []
session_encounters = {}
selected_session = "Session 1: Paint it Black"
encounters_to_add.append("Meet the Town (Narrative)")
session_encounters[selected_session] = encounters_to_add
encounters_to_add.append("Barn Bandits (Structured)")
session_encounters[selected_session] = encounters_to_add
encounters_to_add.clear()
selected_session = "Session 2: Myster Man"
encounters_to_add.append("A Crime Most Foul (Social)")
session_encounters[selected_session] = encounters_to_add
print(session_encounters)
我想回来
{'Session 1: Paint it Black': ['Meet the Town (Narrative)', 'Barn Bandits (Structured)'], 'Session 2: Mystery Man': ['A Crime Most Foul (Social)']}
相反,我回来了
{'Session 1: Paint it Black': ['A Crime Most Foul (Social)'], 'Session 2: Myster Man': ['A Crime Most Foul (Social)']}
我不明白以前的值是如何被覆盖的。由于我使用的是新密钥,因此应该在我脑海中将值添加到该密钥中。
答案 0 :(得分:1)
那是因为您只是存储对在第二行中创建的列表实例的 引用 :
# Creates a new instance of a list where
# 'encounters_to_add' is the reference to this list
encounters_to_add = []
# Stores only a copy of the 'reference' in your dictionary
session_encounters[selected_session] = encounters_to_add
这不是列表的副本 -似乎就是您所假设的-而是对该列表的引用的副本。
您对encounters_to_add
所做的任何事情都会影响session_encounters[selected_session]
,因为
session_encounters[selected_session] = encounters_to_add
session_encounters[selected_session] is encounters_to_add # is True
或更清楚一点:
session_encounters['A'] = encounters_to_add
session_encounters['B'] = encounters_to_add
session_encounters['A'] is encounters_to_add # is True
session_encounters['B'] is encounters_to_add # is also True
您需要两个实例,例如:
encounters_to_add_1 = [] # An instance of a list
encounters_to_add_2 = [] # Another list instance
session_encounters = {}
selected_session = "Session 1: Paint it Black"
encounters_to_add_1.append("Meet the Town (Narrative)")
encounters_to_add_1.append("Barn Bandits (Structured)")
session_encounters[selected_session] = encounters_to_add_1
selected_session = "Session 2: Myster Man"
encounters_to_add_2.append("A Crime Most Foul (Social)")
session_encounters[selected_session] = encounters_to_add_2
print(session_encounters)
输出:
{'Session 1: Paint it Black': ['Meet the Town (Narrative)', 'Barn Bandits (Structured)'], 'Session 2: Myster Man': ['A Crime Most Foul (Social)']}
这是另一个示例-尝试找出此处发生的情况:
my_list = list()
my_dict = {i: my_list for i in range(3)}
my_dict[0].append('Hello World!')
print(my_dict)
my_dict = {i: list() for i in range(3)}
my_dict[0].append('Hello World!')
print(my_dict)
你为什么得到:
{0: ['Hello World!'], 1: ['Hello World!'], 2: ['Hello World!']}
{0: ['Hello World!'], 1: [], 2: []}
答案 1 :(得分:1)
您只有3次插入字典的一个列表,第二次插入将覆盖第一个,因此实际上同一列表最后仅出现两次。在添加之间也要清除它,这就是为什么丢失两个原始条目的原因。只需在print(session_encounters)
调用之后添加一个clear()
。
逐步引导您完成示例:
selected_session = ""
encounters_to_add = []
session_encounters = {}
selected_session = "Session 1: Paint it Black"
encounters_to_add.append("Meet the Town (Narrative)")
session_encounters[selected_session] = encounters_to_add
encounters_to_add.append("Barn Bandits (Structured)")
session_encounters[selected_session] = encounters_to_add
encounters_to_add.clear()
selected_session = "Session 2: Myster Man"
encounters_to_add.append("A Crime Most Foul (Social)")
session_encounters[selected_session] = encounters_to_add
解决方案很简单:始终创建新列表:
session_encounters = {}
selected_session = "Session 1: Paint it Black"
encounters_to_add = ["Meet the Town (Narrative)", "Barn Bandits (Structured)"]
session_encounters[selected_session] = encounters_to_add
selected_session = "Session 2: Myster Man"
encounters_to_add ["A Crime Most Foul (Social)"]
session_encounters[selected_session] = encounters_to_add
print(session_encounters)
请注意,您也可以使用collections.defaultdict
使其更加简单明了:
from collections import defaultdict
session_encounters = defaultdict(list)
session_encounters["Session 1: Paint it Black"].append("Meet the Town (Narrative)")
session_encounters["Session 1: Paint it Black"].append("Barn Bandits (Structured)")
session_encounters["Session 2: Myster Man"].append("A Crime Most Foul (Social)")
print(session_encounters)
答案 2 :(得分:0)
在python中,有两种传递/分配值的方式,按引用或按值。
更新(贷记为 MSeifert ):请注意,默认情况下,Python始终会按引用分配值。上述传递值实际上是由于某些对象类型的不可变性而发生的行为。阅读评论以获取更多详细信息/示例。
您面临的问题是,您将encounters_to_add
列表(通过引用)传递到了字典sessions_encounters
中,然后使用encounters_to_add.clear()
方法重置了对象。这影响了所有对象关联(包括与"Session 1: Paint it Black"
字典内的键session_encounters
关联的值)。
要解决此问题,您需要按照以下代码按值传递encounters_to_add
请注意,唯一的区别在于第
session_encounters[selected_session] = encounters_to_add[:]
行的赋值,其中[:]
将指示python创建列表的本地副本(按值传递)而不是通过引用传递它。
selected_session = ""
encounters_to_add = []
session_encounters = {}
selected_session = "Session 1: Paint it Black"
encounters_to_add.append("Meet the Town (Narrative)")
encounters_to_add.append("Barn Bandits (Structured)")
session_encounters[selected_session] = encounters_to_add[:]
encounters_to_add.clear()
selected_session = "Session 2: Myster Man"
encounters_to_add.append("A Crime Most Foul (Social)")
session_encounters[selected_session] = encounters_to_add[:]
print(session_encounters)
这将输出
{'Session 1: Paint it Black': ['Meet the Town (Narrative)', 'Barn Bandits (Structured)'], 'Session 2: Myster Man': ['A Crime Most Foul (Social)']}