关于切片数组在python中覆盖字典分配的问题

时间:2018-10-05 13:07:29

标签: python arrays dictionary

我有以下代码。我正在尝试使用键“ 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)

1 个答案:

答案 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的内存内容,而没有制作新的内容。