如何在 Python 中初始化空列表的字典?
- 2024-12-18 08:38:00
- admin 原创
- 71
问题描述:
我尝试以编程方式创建列表字典,但无法单独处理字典键。每当我创建列表字典并尝试附加到一个键时,所有键都会更新。这是一个非常简单的测试用例:
data = {}
data = data.fromkeys(range(2),[])
data[1].append('hello')
print data
实际结果:{0: ['hello'], 1: ['hello']}
预期结果:{0: [], 1: ['hello']}
以下是有效的方法
data = {0:[],1:[]}
data[1].append('hello')
print data
实际结果和预期结果:{0: [], 1: ['hello']}
为什么该fromkeys
方法没有按预期发挥作用?
解决方案 1:
当[]
作为第二个参数传递给时dict.fromkeys()
,结果中的所有值dict
将是同一个 list
对象。
在 Python 2.7 或更高版本中,请改用字典推导式:
data = {k: [] for k in range(2)}
在早期版本的 Python 中,没有字典推导式,但可以将列表推导式传递给dict
构造函数:
data = dict([(k, []) for k in range(2)])
在 2.4-2.6 中,还可以将生成器表达式传递给,并且可以删除dict
周围的括号:
data = dict((k, []) for k in range(2))
解决方案 2:
尝试使用defaultdict代替:
from collections import defaultdict
data = defaultdict(list)
data[1].append('hello')
这样,键就不需要提前用空列表初始化。defaultdict()
每次访问尚不存在的键时,对象都会调用给它的工厂函数。因此,在此示例中,尝试访问data[1]
会data[1] = list()
在内部触发,为该键提供一个新的空列表作为其值。
原始代码.fromkeys
共享一个(可变)列表。同样,
alist = [1]
data = dict.fromkeys(range(2), alist)
alist.append(2)
print(data)
将输出{0: [1, 2], 1: [1, 2]}
。文档中提到了dict.fromkeys()
这一点:
所有值都仅引用单个实例,因此值通常是可变对象(例如空列表)是没有意义的。
另一种选择是使用dict.setdefault()
方法,该方法首先检查键是否存在,如果不存在则设置默认值,然后检索键的值。.append
然后可以在结果上调用:
data = {}
data.setdefault(1, []).append('hello')
最后,要从已知键列表和给定的“模板”列表创建字典(其中每个值应该以相同的元素开头,但是是一个不同的列表),请使用字典理解并复制初始列表:
alist = [1]
data = {key: alist[:] for key in range(2)}
这里,alist[:]
创建了 的浅拷贝alist
,并且对每个值分别执行此操作。有关复制列表的更多技术,请参阅如何克隆列表以使其在分配后不会意外更改?
解决方案 3:
您可以使用字典理解:
>>> keys = ['a','b','c']
>>> value = [0, 0]
>>> {key: list(value) for key in keys}
{'a': [0, 0], 'b': [0, 0], 'c': [0, 0]}
解决方案 4:
dict
这个答案是为了向那些对尝试使用fromkeys()
可变默认值实例化所得到的结果感到困惑的人解释这种行为dict
。
考虑:
#Python 3.4.3 (default, Nov 17 2016, 01:08:31)
# start by validating that different variables pointing to an
# empty mutable are indeed different references.
>>> l1 = []
>>> l2 = []
>>> id(l1)
140150323815176
>>> id(l2)
140150324024968
因此对 的任何更改都l1
不会影响l2
,反之亦然。这对于迄今为止的任何可变因素都是正确的,包括dict
。
# create a new dict from an iterable of keys
>>> dict1 = dict.fromkeys(['a', 'b', 'c'], [])
>>> dict1
{'c': [], 'b': [], 'a': []}
这是一个方便的功能。这里我们为每个键分配一个默认值,该默认值恰好是一个空列表。
# the dict has its own id.
>>> id(dict1)
140150327601160
# but look at the ids of the values.
>>> id(dict1['a'])
140150323816328
>>> id(dict1['b'])
140150323816328
>>> id(dict1['c'])
140150323816328
事实上,它们都使用相同的引用!更改一个引用就意味着更改所有引用,因为它们实际上是同一个对象!
>>> dict1['a'].append('apples')
>>> dict1
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']}
>>> id(dict1['a'])
>>> 140150323816328
>>> id(dict1['b'])
140150323816328
>>> id(dict1['c'])
140150323816328
对于许多人来说,这并不是预期的结果!
现在让我们尝试对用作默认值的列表进行明确的复制。
>>> empty_list = []
>>> id(empty_list)
140150324169864
现在用 的副本创建一个字典empty_list
。
>>> dict2 = dict.fromkeys(['a', 'b', 'c'], empty_list[:])
>>> id(dict2)
140150323831432
>>> id(dict2['a'])
140150327184328
>>> id(dict2['b'])
140150327184328
>>> id(dict2['c'])
140150327184328
>>> dict2['a'].append('apples')
>>> dict2
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']}
还是没有结果!我听到有人喊,这是因为我用了一个空列表!
>>> not_empty_list = [0]
>>> dict3 = dict.fromkeys(['a', 'b', 'c'], not_empty_list[:])
>>> dict3
{'c': [0], 'b': [0], 'a': [0]}
>>> dict3['a'].append('apples')
>>> dict3
{'c': [0, 'apples'], 'b': [0, 'apples'], 'a': [0, 'apples']}
的默认行为fromkeys()
是分配None
给该值。
>>> dict4 = dict.fromkeys(['a', 'b', 'c'])
>>> dict4
{'c': None, 'b': None, 'a': None}
>>> id(dict4['a'])
9901984
>>> id(dict4['b'])
9901984
>>> id(dict4['c'])
9901984
确实,所有值都是相同的(而且是唯一的!)None
。现在,让我们以无数种方式之一迭代dict
并更改值。
>>> for k, _ in dict4.items():
... dict4[k] = []
>>> dict4
{'c': [], 'b': [], 'a': []}
嗯。看起来和以前一样!
>>> id(dict4['a'])
140150318876488
>>> id(dict4['b'])
140150324122824
>>> id(dict4['c'])
140150294277576
>>> dict4['a'].append('apples')
>>> dict4
>>> {'c': [], 'b': [], 'a': ['apples']}
但它们确实是不同的[]
,在这种情况下这是预期的结果。
解决方案 5:
你可以使用这个:
l = ['a', 'b', 'c']
d = dict((k, [0, 0]) for k in l)
解决方案 6:
您正在用对单个列表的引用填充您的字典,因此当您更新它时,更新将反映在所有引用中。请尝试使用字典推导式。请参阅
在 Python 中使用列表推导式创建字典
d = {k : v for k in blah blah blah}
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理必备:盘点2024年13款好用的项目管理软件