Python3.4 字典值替换问题
Python3.4 Dictionary value replacement issue
我有一些代码可以获取字典列表并创建另一个字典列表。
列表中的每个字典都有两个 key/value 对 "ID" 和 "opcode",其中 "opcode" 是一个 32 位数。
我的代码需要创建第二个字典列表,其中操作码是分开的,即操作码=5 的字典将变成操作码=1 和操作码=4 的两个字典。
(opcode是一个32位的数字,我的要求是只有1位为高,即opcode=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}
我可以通过以不同的方式解决问题来解决这个问题,但是为了了解正在发生的事情,我无法理解。
这是因为当您将 i
附加到新列表时,您没有创建字典的副本,而是添加了对原始字典的引用。这意味着当您在下一行更改字典时,您也会更改 part
中的值。这导致循环不再匹配操作码的任何部分。如果您在代码末尾打印出 part
的值,您可以看到这一点。
python 文档解释为:
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.
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)
我有一些代码可以获取字典列表并创建另一个字典列表。 列表中的每个字典都有两个 key/value 对 "ID" 和 "opcode",其中 "opcode" 是一个 32 位数。
我的代码需要创建第二个字典列表,其中操作码是分开的,即操作码=5 的字典将变成操作码=1 和操作码=4 的两个字典。
(opcode是一个32位的数字,我的要求是只有1位为高,即opcode=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}
我可以通过以不同的方式解决问题来解决这个问题,但是为了了解正在发生的事情,我无法理解。
这是因为当您将 i
附加到新列表时,您没有创建字典的副本,而是添加了对原始字典的引用。这意味着当您在下一行更改字典时,您也会更改 part
中的值。这导致循环不再匹配操作码的任何部分。如果您在代码末尾打印出 part
的值,您可以看到这一点。
python 文档解释为:
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other. 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)