我有以下代码。我正在尝试使用键“ CH4”和“ NO”向字典添加numpy数组EPtmp(CH4填充为零,NO填充为1)。在for循环的第一次迭代中,零数组与键CH4正确关联。在第二次迭代中,ones数组将覆盖先前写入的CH4键以及新的NO键的条目。如果我从EPtmp [:] = EP中删除切片,使其改为EPtmp = EP,则它将完美地工作而不会覆盖先前写入的数组。这似乎与Python分配或访问内存的方式有关,但是我还无法在文档中找到任何内容来解释这种行为。为什么切片[:]会导致字典覆盖?
import numpy as np
species_names = ['O2', 'CH4', 'NO', 'N2', 'O', 'CH3', 'H', 'HO2', 'N2O', 'NO2', 'NNH']
target_index_species = [1,2]
EP_spec_dict = {}
EPtmp = np.zeros(len(species_names),'d')
for index_target_local, index_target_global in enumerate(target_index_species):
EP = np.ones(len(species_names))*index_target_local
EPtmp[:] = EP
print("Going to add",species_names[index_target_global],"EP tmp",EPtmp)
EP_spec_dict[species_names[index_target_global]] = EPtmp
print("Full dict",EP_spec_dict)
答案 0 :(得分:1)
EPtmp = EP
使EPtmp成为EP的引用,这意味着如果更改EPtmp,则实际上是在更改EP,因为它们是同一阵列。
EPtmp[:]
= EP复制了EP,因此更改EPtmp不会更改EP。
在控制台中尝试以下操作:
a=[1,2]
b=[0,0]
a=b
a[0]=5
b
Out[13]: [5, 0]
和
a=[1,2]
b=[0,0]
a[:]=b
a[0]=5
b
Out[18]: [0, 0]
但是切片也可以相反。如果您有b = a
,然后通过执行a = []来设置a,则b不会更改,因为您正在创建新的a。但是,如果您不创建新的a而是用a[:]=[]
显式覆盖旧的a,则b会更改。
尝试:
a=[1,2]
b=a
c=b
a=[1,3] #doesn't change b and c
b[:]=[1,4] #changes c
基本上,a = b表示a是指向b在内存中指向的指针,而a [:] = b表示将b的内容写入指向a的指针。
因此,在您的示例中,字典包含指向EPtmp的指针。由EP_spec_dict[species_names[index_target_global]] = EPtmp
现在,如果您使用EPtmp=EP
创建新的EPtmp,则该EPtmp位于不同的存储区中,而EP_spec_dict[species_names[index_target_global]]
仍指向旧的EPtmp的存储区。但是,使用EPtmp [:] = EP,您只是覆盖了EPtmp的内存内容,而没有制作新的内容。