Python: 修改包含数组视图的单个字典项会修改所有项
Python: modifying single dictionary item containing an array view modifies all items
我有两本键值相同的字典。每个项目都是一个 ndarray。
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].phase
和 J1[iFld][0,1,:,:] = U1[iFld].amplitude
但我得到 J1[iFld]
对于所有 iFld
都是相同的并且等于所有 iFld
的总和] U1
的键(当然要跟踪 U1
的 phase
和 amplitude
字段)。
对我来说这看起来像是一个错误,但我只使用 Python 一个月左右(从 matlab 切换)所以我不确定。
问题:这是预期的行为还是错误?我应该在我的代码中更改什么以获得我想要的行为?
注意:我选择了dict_keys
、J1
和U1
的维数来反映我的具体情况。
这不是一个错误,尽管它是一个在几种不同情况下出现的非常常见的问题。 dict.fromkeys
创建一个新字典,其中所有值 都是同一个对象 。这对于不可变类型(例如 int
、str
)非常有效,但对于可变类型,您可以 运行 遇到问题。
例如:
>>> 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)
我有两本键值相同的字典。每个项目都是一个 ndarray。
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].phase
和 J1[iFld][0,1,:,:] = U1[iFld].amplitude
但我得到 J1[iFld]
对于所有 iFld
都是相同的并且等于所有 iFld
的总和] U1
的键(当然要跟踪 U1
的 phase
和 amplitude
字段)。
对我来说这看起来像是一个错误,但我只使用 Python 一个月左右(从 matlab 切换)所以我不确定。
问题:这是预期的行为还是错误?我应该在我的代码中更改什么以获得我想要的行为?
注意:我选择了dict_keys
、J1
和U1
的维数来反映我的具体情况。
这不是一个错误,尽管它是一个在几种不同情况下出现的非常常见的问题。 dict.fromkeys
创建一个新字典,其中所有值 都是同一个对象 。这对于不可变类型(例如 int
、str
)非常有效,但对于可变类型,您可以 运行 遇到问题。
例如:
>>> 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)