Mint Cinnamon上的Python 2.7 17.3。 我有一些测试代码采用了一系列的dicts,尽管经历了几个小时的挫折,我似乎无法弄清楚为什么它不能正常工作。
blockagedict = {'location': None, 'timestamp': None, 'blocked': None}
blockedlist = [blockagedict]
blockagedict['location'] = 'A'
blockagedict['timestamp'] = '12-Apr-2016 01:01:08.702149'
blockagedict['blocked'] = True
blockagedict['location'] = 'B'
blockagedict['timestamp'] = '12-Apr-2016 01:01:09.312459'
blockagedict['blocked'] = False
blockedlist.append(blockagedict)
for test in blockedlist:
print test['location'], test['timestamp'], test['blocked']
这总是产生以下输出,我无法弄清楚为什么,也看不出我的代码是否有任何问题。它总是打印出最后一组dict值,但是如果我没有弄错的话,应该打印全部。
B 12-Apr-2016 01:01:09.312459 False
B 12-Apr-2016 01:01:09.312459 False
我很高兴有人向我展示我的方式的错误,并让我摆脱痛苦。
答案 0 :(得分:4)
这是因为行blockedlist = [blockagedict]
实际上在列表中存储了对dict的引用,而不是副本。您的代码有效地创建了一个列表,该列表具有对同一对象的两个引用。
答案 1 :(得分:1)
如果您关心性能并且列表中有100万个字典,所有字典都使用相同的键,那么最好使用NumPy结构化数组。然后,您可以拥有一个单一,高效的数据结构,该结构基本上是行的矩阵和适当类型的命名列。您在评论中提到您可能事先知道行数。这里是使用NumPy重写你的示例代码,它将比一百万个dicts的列表更加高效。
import numpy as np
dtype = [('location', str, 1), ('timestamp', str, 27), ('blocked', bool)]
count = 2 # will be much larger in the real program
blockages = np.empty(count, dtype) # use zeros() instead if some data may never be populated
blockages[0]['location'] = 'A'
blockages[0]['timestamp'] = '12-Apr-2016 01:01:08.702149'
blockages[0]['blocked'] = True
blockages['location'][1] = 'B' # n.b. indexing works this way too
blockages['timestamp'][1] = '12-Apr-2016 01:01:09.312459'
blockages['blocked'][1] = False
for test in blockages:
print test['location'], test['timestamp'], test['blocked']
请注意,使用情况几乎相同。但是存储是固定大小的单一分配。这将减少内存使用量和计算时间。
作为一个很好的副作用,如上所述,完全回避你最初的问题,多次引用同一行。现在所有数据都直接放入矩阵中,根本没有对象引用。
稍后您在评论中提到您无法使用NumPy,因为它可能未安装。好吧,我们仍然可以避免不必要的决定,例如:
from array import array
blockages = {'location': [], 'timestamp': [], 'blocked': array('B')}
blockages['location'].append('A')
blockages['timestamp'].append('12-Apr-2016 01:01:08.702149')
blockages['blocked'].append(True)
blockages['location'].append('B')
blockages['timestamp'].append('12-Apr-2016 01:01:09.312459')
blockages['blocked'].append(False)
for location, timestamp, blocked in zip(*blockages.values()):
print location, timestamp, blocked
注意我在这里使用array
来有效存储固定大小的blocked
值(这样每个值只需要一个字节)。
您仍然可以避免使用可调整大小的列表,但至少您不需要在列表的每个插槽中存储dict。这应该更有效率。
答案 2 :(得分:0)
好的,我已经初步确定了蝙蝠的名单,这似乎有效。虽然我很想为此写一堂课。
blockedlist = [{'location': None, 'timestamp': None, 'blocked': None} for k in range(2)]
blockedlist[0]['location'] = 'A'
blockedlist[0]['timestamp'] = '12-Apr-2016 01:01:08.702149'
blockedlist[0]['blocked'] = True
blockedlist[1]['location'] = 'B'
blockedlist[1]['timestamp'] = '12-Apr-2016 01:01:09.312459'
blockedlist[1]['blocked'] = False
for test in blockedlist:
print test['location'], test['timestamp'], test['blocked']
这就产生了我想要的东西:
A 12-Apr-2016 01:01:08.702149 True
B 12-Apr-2016 01:01:09.312459 False
我将从一个包含1到2百万行的文本文件中读取,因此转换代码以迭代这些行不会成为问题。