我得到一个与你不同的错误(使用 numpy 1.7.0.dev):
ValueError: setting an array element with a sequence.
所以下面的解释可能对你的系统不正确(或者它甚至可能是我所看到的错误解释)。
首先,请注意,索引structured array 的一行会为您提供numpy.void 对象(请参阅data type docs)
import numpy as np
dt = np.dtype([('tuple', (int, 2))])
a = np.zeros(3, dt)
print type(a[0]) # = numpy.void
据我了解,void 有点像 Python 列表,因为它可以保存不同数据类型的对象,这是有道理的,因为结构化数组中的列可以是不同的数据类型。
如果不是索引,而是切掉第一行,你会得到一个ndarray:
print type(a[:1]) # = numpy.ndarray
这类似于 Python 列表的工作方式:
b = [1, 2, 3]
print b[0] # 1
print b[:1] # [1]
切片返回原始序列的缩短版本,但索引返回一个元素(此处为int;上为void 类型)。
因此,当您对结构化数组的行进行切片时,您应该期望它的行为与您的原始数组一样(只有更少的行)。继续您的示例,您现在可以分配给第一行的“元组”列:
a[:1]['tuple'] = (1, 2)
那么,...为什么a[0]['tuple'] = (1, 2) 不起作用?
好吧,回想一下 a[0] 返回一个 void 对象。所以,当你打电话时
a[0]['tuple'] = (1, 2) # this line fails
您将 tuple 分配给该 void 对象的“元组”元素。 注意:尽管您将此索引称为“元组”,但它仍存储为ndarray:
print type(a[0]['tuple']) # = numpy.ndarray
因此,这意味着需要将元组转换为 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 # = True
print a[0].base is a # = False
a[0] = ((1, 2),) # `a` is changed
也许void 不是真正的数组,所以它没有基本数组,...但是为什么它有base 属性?