在循环中生成列表字典 (3.2.3)

Generating dictionary of lists in a loop (3.2.3)

我需要创建一个字典,其中键是一个字符串,值是一个列表。诀窍是我需要循环执行。

目前我的最小化代码如下所示:

for elem in xmlTree.iter():

  # skipping root element
  if elem.tag == xmlTree.getroot().tag:
    continue
  # this is supposed to be my temporary list
  tmpList = []
  for child in elem:
      tableWColumns[elem.tag] = tmpList.append(child.tag)
print(tableWColumns)

这仅打印在上次迭代中创建的列表。

问题显然在于每当我更改列表时,它的所有引用也会随之更改。我用谷歌搜索了那个。我没有用谷歌搜索过的是在使用循环时如何处理它。

当我想保留列表时,我应该使用的解决方案是将它复制到其他列表,然后我可以在不丢失数据的情况下更改原始列表。当我基本上需要动态地执行此操作时,我不知道该怎么做。

此外,我仅限于使用标准库。

问题是因为你在每次迭代中创建 tmpList = [] 列表并将其放入 []。所以 python 在每次迭代中用旧的替换新的,因此你查看列表中的最后一次迭代结果。

您可以使用 collections.defaultdict :

from collections import defaultdict
d=defaultdict(list)

for elem in xmlTree.iter():
  # skipping root element
  if elem.tag == xmlTree.getroot().tag:
    continue
  # this is supposed to be my temporary list
  for child in elem:
      d[elem.tag].append(child.tag)
print(tableWColumns)

或者你可以使用dict.setdefault方法:

d={}
for elem in xmlTree.iter():
  # skipping root element
  if elem.tag == xmlTree.getroot().tag:
    continue
  # this is supposed to be my temporary list
  for child in elem:
      d.setdefault(elem.tag,[]).append(child.tag)
print(tableWColumns)

另请注意,@abarnert 说 tmpList.append(child.tag) 将 return None。所以实际上在分配后 python 会将 None 分配给 tableWColumns[elem.tag] .

这里的大问题是 tmpList.append(child.tag) returns None。事实上,Python return None.

中几乎所有的变异方法

要解决这个问题,您可以进行突变,然后在单独的语句中插入值:

for child in elem:
    tmpList.append(child.tag)
tableWColumns[elem.tag] = tmpList

… 或者一开始就不要尝试改变列表。例如

tableWColumns[elem.tag] = tmpList + [child.tag for child in elem]

这将解决您的所有值都是 None 的问题,但是您又遇到了一个新问题。如果任何标签出现不止一次,您只能从该标签的最后一个副本中获取子项,而不是从所有副本中获取。那是因为您每次都构建一个新列表,然后将 tableWColumns[elem.tag] 重新分配给该新列表,而不是修改其中的任何内容。

要解决该问题,您需要将现有值提取到 tmpList 而不是创建新值:

tmpList = tableWColumns.get(elem.tag, [])
tableWColumns[elem.tag] = tmpList + [child.tag for child in elem]

或者,如 所说,您可以使用 defaultdictsetdefault 方法来简化它。