Вопрос о нарезке массивов, переопределяющих словарь в Python - PullRequest
0 голосов
/ 05 октября 2018

У меня есть следующий код.Я пытаюсь добавить к словарю массив EPtmp (заполненный нулями для CH4, заполненный единицами для NO) с ключами 'CH4' и 'NO'.На первой итерации цикла 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 голосов
/ 05 октября 2018

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[:]=[], изменяется 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 с EPtmp=EP, он находится в другом разделе памяти, а EP_spec_dict[species_names[index_target_global]] по-прежнему указывает на старый раздел памяти EPtmp.Однако с EPtmp [:] = EP вы просто перезаписываете содержимое памяти EPtmp, а не делаете новый.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...