
上QQ阅读APP看书,第一时间看更新
2.5.3 与结构数组共享内存
从结构数组获取某个字段时,得到的是原数组的视图,但是如果获取多个字段,将得到一个全新的数组,不与原数组共享内存。
persontype = np.dtype({ 'names':['name', 'age', 'weight', 'height'], 'formats':['S30','i', 'f', 'f']}, align= True ) a = np.array([("Zhang", 32, 72.5, 167.0), ("Wang", 24, 65.2, 170.0)], dtype=persontype) print a["age"].base is a #视图 print a[["age", "height"]].base is None #复制 True True
为了创建结构数组的多字段视图,可以使用下面的fields_view( )函数。它通过原数组的dtype属性创建视图数组的dtype对象。然后通过ndarray( )创建视图数组。
def fields_view(arr, fields): dtype2 = np.dtype({name:arr.dtype.fields[name] for name in fields}) return np.ndarray(arr.shape, dtype2, arr, 0, arr.strides) v = fields_view(a, ["age", "weight"]) print v.base is a v["age"] += 10 print a True [('Zhang', 42, 72.5, 167.0) ('Wang', 34, 65.19999694824219, 170.0)]
dtype对象的fields属性是一个以字段名为键、以字段类型和字节偏移量为值的字典,使用它创建新的dtype对象时,可以保持字段的偏移量:
print a.dtype.fields print a.dtype print v.dtype {'age': (dtype('int32'), 32), 'name': (dtype('S30'), 0), 'weight': (dtype('float32'), 36), 'height': (dtype('float32'), 40)} {'names':['name','age','weight','height'], 'formats':['S30','<i4','<f4','<f4'], 'offsets':[0,32,36,40], 'itemsize':44, 'aligned':True} {'names':['age','weight'], 'formats':['<i4','<f4'], 'offsets':[32,36], 'itemsize':40}
如果这两个dtype对象的itemsize属性相同,那么可以使用数组的view( )方法创建视图对象。但是从上面的输出可以看到两个dtype对象的字节数并不相同,一个是44个字节,另一个是40个字节。遇到这种情况时,可以使用ndarray( )创建数组的视图,它的调用参数如下:
ndarray(shape, dtype=float, buffer=None, offset=0, strides=None, order=None)
●shape:所创建数组的形状。
●dtype:数组元素类型的dtype对象。
●buffer:拥有buffer接口的对象,所创建的数组将与该对象共享内存。
●offset:buffer对象的数据内存中的起始地址的偏移量。
●strides:所创建数组的strides属性,即每个轴上的下标增加1时的地址增量。
●order:C语言格式或Fortran语言格式。
在fields_view( )中,我们所创建的数组视图与原数组拥有相同的shape、data和strides属性。而dtype属性中的字段与原数组拥有相同的偏移量,显然这样的新数组能够与原数组共享内存。