在Raspbian Pi的Raspbian上的Spyder 3.1.3中使用Python3.5.3。 将两个numpy数组附加到名为“ list0”的列表中,可以很好地与分配的numpy数组“ a”一起使用,例如:
import numpy as np
list0 = []
a = np.array([[1,2,3],[2,3,4]])
list0.append(a)
a = np.array([[11,12,13],[12,13,14]])
list0.append(a)
print("list0 =",list0)
效果很好,可以作为输出(为帖子提供更好的格式):
list0 = [ array([[ 1, 2, 3], [ 2, 3, 4]]),
array([[11, 12, 13], [12, 13, 14]]) ]
使用循环将分配替换为a,会发生奇怪的事情:
import numpy as np
a = np.empty((3), int)
list0 = []
for idx in range(4):
for i in range(3):
a[i] = idx*10 + i
print("idx =",idx,"; a =",a)
list0.append(a)
print("list0 =",list0)
第二行告诉Python使用的数组的形状(在我的原始情况下,它是三维数组)。为了进行验证,将生成的名为“ a”的数组打印出来。最后,将新填充的数组'a'添加到'list0'会显示最后一行的四倍。
idx = 0 ; a = [ 0 1 2]
idx = 1 ; a = [10 11 12]
idx = 2 ; a = [20 21 22]
idx = 3 ; a = [30 31 32]
list0 = [ array([30, 31, 32]), array([30, 31, 32]),
array([30, 31, 32]), array([30, 31, 32]) ]
我想'list0'有时仅包含一个指向数组'a'的指针,该数组仅存在于一个实例/内存范围内。
所以:我如何物理上将每个不同的数组“ a”追加(复制?)到列表中?是python的bug还是仅仅是我对某些东西的误解?当然,我应该考虑更多的pythonian; c)
感谢您的帮助,彼得
答案 0 :(得分:3)
您要将相同的数组a
附加到list0
4次。像a
这样的数组是可变对象,这意味着,除其他事项外,当您为它们分配值时,基础对象也会更改。由于阵列在您的列表中出现了4次,因此这些更改(似乎)显示在4个不同的位置。
只需少量更改,即可修复您拥有的代码。将数组的副本而不是数组本身附加到列表中:
import numpy as np
a = np.empty((3), int)
list0 = []
for idx in range(4):
for i in range(3):
a[i] = idx*10 + i
print("idx =",idx,"; a =",a)
list0.append(a.copy())
print("list0 =",list0)
输出:
idx = 0 ; a = [0 1 2]
idx = 1 ; a = [10 11 12]
idx = 2 ; a = [20 21 22]
idx = 3 ; a = [30 31 32]
list0 = [array([0, 1, 2]), array([10, 11, 12]), array([20, 21, 22]), array([30, 31, 32])]
Python / Numpy提供了许多更好的方法(就使用更少的代码行和更快的速度而言)来初始化数组。对于这样的范围,这里是一种合理的方法:
list0 = [np.arange(n*10, n*10+3) for n in range(4)]
print(list0)
输出:
[array([0, 1, 2]), array([10, 11, 12]), array([20, 21, 22]), array([30, 31, 32])]
您可能还考虑仅使用单个2D数组来代替数组列表。一个单一的数组通常比列表中数组的异构混合更容易使用。操作方法如下:
arr0 = np.array([np.arange(n*10, n*10+3) for n in range(4)])
print(arr0)
输出:
[[ 0 1 2]
[10 11 12]
[20 21 22]
[30 31 32]]
答案 1 :(得分:1)
只需执行以下操作:
list_to_append.append(np_array.copy())
在壳中,numpy数组或列表是可变对象,这意味着当您将numpy数组或列表分配给变量时,您实际上是在分配什么是对内存位置(也称为指针)的引用。
在您的情况下,“ a”是一个指针,因此您实际要做的是在list0后面附加一个由“ a”指向的内存位置的地址,而不是指针指向的实际值。 因此,这意味着“ list0”的每个新位置在追加后都会变成相同的内存地址:“ a”。
所以,而不是:
list0.append(a)
您调用“ a”的copy()方法,该方法为“ a”的新值创建一个新的存储位置并返回:
list0.append(a.copy())