我遇到的错误不同于你的(使用numpy 1.7.0.dev):
ValueError: setting an array element with a sequence.
因此,下面的解释可能不适用于您的系统(或者甚至可能是我所看到的错误解释)。
首先,请注意索引一个
结构数组的行将给您一个
numpy.void
对象(请参见
数据类型文档)。
import numpy as np
dt = np.dtype([('tuple', (int, 2))])
a = np.zeros(3, dt)
print type(a[0])
据我所了解,
void
类似于 Python 中的列表,因为它可以保存不同数据类型的对象。这很有道理,因为结构化数组中的列可以是不同的数据类型。
如果您不使用索引而是切片获取第一行,你会得到一个
ndarray
:
print type(a[:1])
这类似于Python列表的工作方式:
b = [1, 2, 3]
print b[0]
print b[:1]
切片可以返回原始序列的缩短版本,而索引则返回一个元素(此处为int类型;上面是void类型)。
因此,当你切片结构化数组的行时,你应该期望它的行为与原始数组相同(只是少了几行)。按照你的例子继续进行,现在你可以对第一行的'tuple'列进行赋值。
a[:1]['tuple'] = (1, 2)
所以,为什么 a[0]['tuple'] = (1, 2)
不起作用呢?
好的,回想一下 a[0]
返回一个 void
对象。因此,当你调用
a[0]['tuple'] = (1, 2)
你正在将一个tuple
分配给该void
对象的'tuple'元素。 注意: 尽管你将此索引称为“tuple”,但它存储为ndarray
:
print type(a[0]['tuple'])
因此,这意味着元组需要转换为一个ndarray
。然而,void
对象不能进行转换赋值(这只是一个猜测),因为它可以包含任意数据类型,所以它不知道要转换成什么类型。为了解决这个问题,您可以自己进行转换:
a[0]['tuple'] = np.array((1, 2))
我们收到不同的错误提示,这意味着上述行可能对您无效,因为强制转换只解决了我收到的错误,而没有解决您收到的错误。
补充:
那么为什么以下代码可以工作呢?
a[0]['tuple'][:] = (1, 2)
在这里,当你添加
[:]
时,你正在数组中进行索引,但是没有添加它时,你正在
void
对象中进行索引。换句话说,
a[0]['tuple'][:]
表示“替换存储的数组元素”(由数组处理),
a[0]['tuple']
表示“替换存储的数组”(由
void
处理)。
结语:
奇怪的是,访问行(即使用0进行索引)似乎会丢失基本数组,但仍然允许您对基本数组进行赋值。
print a['tuple'].base is a
print a[0].base is a
a[0] = ((1, 2),)
也许
void
不是真正的数组,所以它没有基本数组,... 但为什么它有一个
base
属性呢?
a[0]['tuple'][:] = (1,2)
可以工作,也许那里有一些线索... - Ricardo Cárdenes