1

我有兩個具有相同鍵的字典。每個項目是一個ndarray。Python:修改包含數組視圖的單個字典項目修改所有項目

from numpy import zeros, random 
from collections import namedtuple 

PhaseAmplitude = namedtuple('PhaseAmplitude','phase amplitude') 
dict_keys = {'K1','K2', 'K3'} 

J1 = dict.fromkeys(dict_keys, zeros((2,2,2,2))) 
U1 = dict.fromkeys(dict_keys, PhaseAmplitude(phase = zeros((2,2)), 
              amplitude = zeros((2,2)))) 

for iFld in dict_keys: 
    U1[iFld] = U1[iFld]._replace(phase = random.random_sample((2,2)), 
           amplitude = random.random_sample((2,2))) 

我想用在第二個相應的項目來修改第一庫的每個項目:

for iFld in dict_keys: 
    J1[iFld][0,0,:,:] += U1[iFld].phase 
    J1[iFld][0,1,:,:] += U1[iFld].amplitude 

我期望得到的是J1[iFld][0,0,:,:] = U1[iFld].phaseJ1[iFld][0,1,:,:] = U1[iFld].amplitude但我得到J1[iFld]是相同的全部爲iFld並且等於U1的所有iFld鍵的總和(當然保持跟蹤phaseamplitude字段的U1)。

對我來說這看起來像一個錯誤,但我一直只使用Python一個月左右(從matlab切換),所以我不確定。

問題:這是預期的行爲還是錯誤?爲了獲得我想要的行爲,我應該在代碼中更改哪些內容?

注:我選擇的dict_keysJ1U1維數,以反映我的特殊情況。

+0

Python字典值就像指針,我猜所有的鍵都指向同一個對象。你可以使用內建'id'函數或'is'運算符來檢查它們是否是同一個對象。如果是這種情況,請使用'dict.copy'方法。 –

回答

1

這不是一個錯誤,雖然它是一個很常見的陷阱,出現在幾種不同的情況。 dict.fromkeys創建一個新字典,其中所有值是相同的對象。這適用於不可變類型(例如intstr),但對於可變類型,可能會遇到問題。

如:

>>> import numpy as np 
>>> d = dict.fromkeys('ab', np.zeros(2)) 
>>> d 
{'a': array([ 0., 0.]), 'b': array([ 0., 0.])} 
>>> d['a'][1] = 1 
>>> d 
{'a': array([ 0., 1.]), 'b': array([ 0., 1.])} 

,這是因爲:

>>> d['a'] is d['b'] 
True 

使用字典理解構建字典在這種情況下:

J1 = {k: zeros((2,2,2,2)) for k in dict_keys} 

(或預python2 .7):

J1 = dict((k, zeros((2,2,2,2))) for k in dict_keys) 
+0

是的,這個工作!感謝您的詳細回覆! – rtphase