这是我之前的一个问题的后续帖子:Referring to arrays in a for-loop。
我想概括那里提出的解决方案,以便能够完成更复杂的任务,例如将列附加到包含某些计算结果的每个数组:
import numpy as np
list=[one, two, three]
for arr in list:
arr=np.column_stack([arr,5*arr[:,2]-arr[:,1])])
所有三个阵列都具有相同的尺寸。
In [59]: one=np.arange(6).reshape(2,3)
In [60]: two=np.arange(6).reshape(2,3)
暂时忘掉循环,试着改变one
:
In [61]: arr = one
In [62]: arr=np.column_stack([arr,5*arr[:,2]-arr[:,1]])
In [63]: arr
Out[63]:
array([[ 0, 1, 2, 9],
[ 3, 4, 5, 21]])
In [65]: one
Out[65]:
array([[0, 1, 2],
[3, 4, 5]])
这个动作改变了arr
,但没有改变one
。最初arr
引用了与ndarray
相同的对象(one
),但在新赋值之后,它引用了一个新数组。
在
for arr in alist:
arr = ....
arr
被分配了alist
元素。但是在循环中,它会被分配另一个别的东西,而不会改变原始对象。在下一次迭代中,arr
被分配列表中的下一个元素,依此类推。
你需要记住几件事。
column_stack
在您之前的问题中
In [69]: for arg in [one,two]:
...: arg[:,1:] += 10
...:
In [70]: one
Out[70]:
array([[ 0, 11, 12],
[ 3, 14, 15]])
In [71]: two
Out[71]:
array([[ 0, 11, 12],
[ 3, 14, 15]])
这是因为arg[:,1:] += 10
正在修改当前分配给arg
的数组。一个数组是mutable
;元素值可以就地更改。
np.column_stack()
没有就地行动。它创建了新阵列。
关于使用列表更改one
和two
的唯一方法是一系列操作,例如:
In [72]: newlist=[np.column_stack([arr,5*arr[:,2]-arr[:,1]]) for arg in [one,two]]
In [73]: newlist
Out[73]:
[array([[ 0, 1, 2, 9, 9],
[ 3, 4, 5, 21, 21]]), array([[ 0, 1, 2, 9, 9],
[ 3, 4, 5, 21, 21]])]
In [74]: one
Out[74]:
array([[ 0, 11, 12],
[ 3, 14, 15]])
In [75]: one, two = newlist
In [76]: one
Out[76]:
array([[ 0, 1, 2, 9, 9],
[ 3, 4, 5, 21, 21]])
In[72]
使用新数组创建一个新列表。 In[75]
将这些新数组分配给变量one
和two
。这抹去了他们以前的参考文献。实际上我做了one=[np.column_stack([one,5*one[:,2]-one[:,1]])
,同样对two
。
分配给变量不会更新列表,它只是对数组中值的临时引用。
使用enumerate
获取列表索引,然后您可以将其替换为结果。
for index, arr in enumerate(myList):
myList[index] = np.column_stack([arr,5*arr[:,2]-arr[:,1])])
另外,请避免使用内置类和函数的名称作为您自己的变量名。 list
是一个标准类。
不要忘记在Python中,变量是对值的引用。迭代变量是一个变量,因此为此变量赋值不会更改迭代。
在这种情况下,为什么不使用列表推导?
import numpy as np
my_list = [one, two, three]
my_list = [np.column_stack([arr,5*arr[:,2]-arr[:,1])]) for arr in list]
请,请不要影子list
type ...
我担心您引用的解决方案只能推广到数组的就地更改。任何改变大小的东西都将AFAIK创建一个新阵列。
所以这
>>> X,Y,Z = (np.arange(i+1, i+10, dtype=float).reshape(3, 3) for i in range(3))
>>> L = [X,Y,Z]
>>> for arr in L:
... np.sin(arr, out=arr)
或这个
>>> for arr in L:
... arr[1] = arr[1, ::-1]
将工作。
您可以替换整个阵列,只要您就地执行:
>>> for arr in L:
... arr[...] = 1.7
但是这个
>>> for arr in L:
... np.append(arr, arr[-1])
不会更改原始数组但会创建新数组。分配回arr
无济于事,因为它只是将名称arr
重新绑定到新对象。