Python 子类化和扩展numpy.ndarray
我需要一些基本的数据类表示,我想使用现有的numpy类,因为它们已经提供了很好的功能 然而,我不确定这是否是一种方法(尽管到目前为止它是有效的)。下面是一个例子:Python 子类化和扩展numpy.ndarray,python,numpy,subclassing,multidimensional-array,Python,Numpy,Subclassing,Multidimensional Array,我需要一些基本的数据类表示,我想使用现有的numpy类,因为它们已经提供了很好的功能 然而,我不确定这是否是一种方法(尽管到目前为止它是有效的)。下面是一个例子: Position类应该像一个简单的numpy.array,但它应该将属性.x、.y和.z映射到三个数组组件。我重写了\uu new\uu方法,该方法返回带有初始数组的ndarray。为了允许访问和修改数组,我为每个数组定义了属性和setter import numpy as np class Position(np.ndarray
Position
类应该像一个简单的numpy.array
,但它应该将属性.x
、.y
和.z
映射到三个数组组件。我重写了\uu new\uu
方法,该方法返回带有初始数组的ndarray
。为了允许访问和修改数组,我为每个数组定义了属性和setter
import numpy as np
class Position(np.ndarray):
"""Represents a point in a 3D space
Adds setters and getters for x, y and z to the ndarray.
"""
def __new__(cls, input_array=(np.nan, np.nan, np.nan)):
obj = np.asarray(input_array).view(cls)
return obj
@property
def x(self):
return self[0]
@x.setter
def x(self, value):
self[0] = value
@property
def y(self):
return self[1]
@y.setter
def y(self, value):
self[1] = value
@property
def z(self):
return self[2]
@z.setter
def z(self, value):
self[2] = value
然而,对于这样一个基本逻辑来说,这似乎有点太多的代码了,我想知道我是否用了“正确”的方法。我还需要一堆其他类,比如
Direction
,这些类将具有许多其他功能(改变时自动规范等),在我开始集成numpy之前,我想问你…我认为ndarray在这里是错误的选择,你可能想要一个简单的命名元组
>>> import collections
>>> Position = collections.namedtuple('Positions', 'x y z')
>>> p = Position(1, 2, 3)
>>> p
Positions(x=1, y=2, z=3)
你可以像这样打开包装
>>> x, y, z = p
>>> x, y, z
(1, 2, 3)
>>>
到目前为止,您所拥有的看起来非常像pandas.dataframe(我自己并没有使用过它们…)。否则它看起来很标准。对你来说,哪一个更重要,代表一个点,还是用数千个点来做数学?我开始使用
(N,3)
数组(或(3,N)
),并编写一些函数来访问选定的列。对我来说,最重要的是如何正确扩展数组,正如标题所说。Position
只是一个很小的例子。我非常想要ndarray
功能,比如点积、矩阵运算和所有其他numpy额外功能。扩展namedtuple
以支持它们需要做更多的工作。这取决于您的情况,但命名元组是专门为类似于您上面概述的示例的情况而设计的。我不认为numpy的视图功能对三项数组有什么用处。您可以使用带有map/reduce/comprehension的普通python来处理产品,例如Position(*map(lambda x:x*3,p))
。更多例子请参见。在我的分析中,我得到了数十万个位置、方向等,以及许多计算和矩阵变换。大多数算法都需要numpy数组,这就是为什么在我的例子中它必须是类似numpy的。谢谢你的回答,但这并不能解决我的特殊问题。@septi:数十万个3元素numpy数组是缓慢的秘诀。如果您关心性能,则需要将数据重新组织为几个大的numpy数组,理想情况下,将计算表示为在整个大数组上完成。否则,您的代码实际上会比使用Python列表(或namedtuples)慢。当然,在某个时候可能会有一个优化过程,但目前我尝试使用“已经存在”的任何东西,大部分内容都是阵列上的linalg操作。顺便说一句,3D位置只是一个例子。不过,谢谢你。