如果我们把你的列表变成一个数组,我们会得到一个二维的对象数组
In [1941]: A = [[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0], [0], [0]]]
In [1942]: A = np.array(A)
In [1943]: A.shape
Out[1943]: (2, 3)
In [1944]: A
Out[1944]:
array([[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0], [0], [0]]], dtype=object)
当我尝试A+1 时,它会遍历A 的元素并尝试为每个元素执行+1。在数值数组的情况下,它可以在快速编译的代码中做到这一点。对于对象数组,它必须为每个元素调用+ 操作。
In [1945]: A+1
...
TypeError: can only concatenate list (not "int") to list
让我们在A 上进行平面迭代再试一次:
In [1946]: for a in A.flat:
...: print(a+1)
....
TypeError: can only concatenate list (not "int") to list
A 的元素是列表; + 表示列表是一个连接:
In [1947]: for a in A.flat:
...: print(a+[1])
...:
[0, 0, 0, 1]
[0, 0, 0, 1]
[0, 0, 0, 1]
[0, 1]
[0, 1]
[0, 1]
如果A 的元素本身是数组,我认为+1 可以工作。
In [1956]: for i, a in np.ndenumerate(A):
...: A[i]=np.array(a)
...:
In [1957]: A
Out[1957]:
array([[array([0, 0, 0]), array([0, 0, 0]), array([0, 0, 0])],
[array([0]), array([0]), array([0])]], dtype=object)
In [1958]: A+1
Out[1958]:
array([[array([1, 1, 1]), array([1, 1, 1]), array([1, 1, 1])],
[array([1]), array([1]), array([1])]], dtype=object)
为了回到纯列表形式,我们将tolist 应用于对象数组的元素和数组本身:
In [1960]: A1=A+1
In [1961]: for i, a in np.ndenumerate(A1):
...: A1[i]=a.tolist()
In [1962]: A1
Out[1962]:
array([[[1, 1, 1], [1, 1, 1], [1, 1, 1]],
[[1], [1], [1]]], dtype=object)
In [1963]: A1.tolist()
Out[1963]: [[[1, 1, 1], [1, 1, 1], [1, 1, 1]], [[1], [1], [1]]]
这是向嵌套列表的所有元素添加值的一种相当圆的方法。我可以通过一次迭代来做到这一点:
In [1964]: for i,a in np.ndenumerate(A):
...: A[i]=[x+1 for x in a]
...:
In [1965]: A
Out[1965]:
array([[[1, 1, 1], [1, 1, 1], [1, 1, 1]],
[[1], [1], [1]]], dtype=object)
所以对对象数组进行数学运算是偶然的。某些操作确实会传播到元素,但即使是这些操作也取决于元素的行为方式。