我有一些代码可以获取字典列表并创建另一个字典列表。 列表中的每个字典都有两个键/值对“ID”和“操作码”,其中“操作码”是32位数字。
我的代码需要创建第二个字典列表,其中操作码是分开的,即opcode = 5的字典将成为opcode = 1且opcode = 4的两个字典。
(操作码是32位数,我的要求是只有1位高,即操作码= 1,2,4,8,16等)
我已将问题简化为以下内容;我的代码需要转为:
part=[{"ID":1,"opcode":4},{"ID":2,"opcode":5},{"ID":3,"opcode":6}]
进入这个:
part_=[{"ID":1,"opcode":4},{"ID":2,"opcode":1},{"ID":2,"opcode":4},{"ID":3,"opcode":2},{"ID":3,"opcode":4}]
目前我的代码如下
def bit_set(theNumber,bit):
return theNumber&(1<<bit)!=0
part=[{"ID":1,"opcode":4},{"ID":2,"opcode":5},{"ID":3,"opcode":6}]
part_=[]
for i in part:
for j in range(32):
if bit_set(i["opcode"],j):
part_.append(i)
part_[-1]["opcode"]=(1<<j)
for i in part_:
print(i)
代码的输出是:
{'opcode': 4, 'ID': 1}
{'opcode': 1, 'ID': 2}
{'opcode': 2, 'ID': 3}
有趣的是,如果我稍微修改代码以使值修改行不存在,则会创建额外的词典 ,但显然操作码不正确。
def bit_set(theNumber,bit):
return theNumber&(1<<bit)!=0
part=[{"ID":1,"opcode":4},{"ID":2,"opcode":5},{"ID":3,"opcode":6}]
part_=[]
for i in part:
for j in range(32):
if bit_set(i["opcode"],j):
part_.append(i)
#part_[-1]["opcode"]=(1<<j)
for i in part_:
print(i)
输出
{'ID': 1, 'opcode': 4}
{'ID': 2, 'opcode': 5}
{'ID': 2, 'opcode': 5}
{'ID': 3, 'opcode': 6}
{'ID': 3, 'opcode': 6}
我可以通过以不同的方式解决问题来解决这个问题,但是为了了解正在发生的事情,我已经超出了我的深度。
答案 0 :(得分:0)
这是因为当您将i
附加到新列表时,您不会创建字典的副本,而是添加对原始字典的引用。这意味着当您在下一行中更改字典时,您还会更改part
中的值。这导致循环不匹配操作码的任何更多部分。如果您在代码末尾打印出part
的值,则可以看到此内容。
python文档将其解释为:
Python中的赋值语句不复制对象,它们在目标和对象之间创建绑定。对于可变或包含可变项的集合,有时需要一个副本,因此可以更改一个副本而不更改另一个副本。 Reference
您可以通过在追加字典时创建字典副本来解决此问题。这将允许您更改值而不影响原始字典。 Python允许您使用copy
模块(Documentation)复制对象。
只需导入copy
,然后执行part_.append(copy.copy(i))
而不是part_.append(i)
。
import copy
def bit_set(theNumber,bit):
return theNumber&(1<<bit)!=0
part = [{"ID": 1, "opcode": 4}, {"ID": 2, "opcode": 5}, {"ID": 3, "opcode": 6}]
part_=[]
for i in part:
for j in range(32):
if bit_set(i["opcode"],j):
part_.append(copy.copy(i))
part_[-1]["opcode"]=(1<<j)
for i in part_:
print(i)