Python3.4字典值替换问题

时间:2015-02-15 11:12:13

标签: python-3.x dictionary

我有一些代码可以获取字典列表并创建另一个字典列表。 列表中的每个字典都有两个键/值对“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}

我可以通过以不同的方式解决问题来解决这个问题,但是为了了解正在发生的事情,我已经超出了我的深度。

1 个答案:

答案 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)