【问题标题】:Howto create python arrays with a "struct" as data-type and custom methods如何使用“结构”作为数据类型和自定义方法创建 python 数组
【发布时间】:2014-08-06 13:45:12
【问题描述】:

我正在从 MATLAB 迁移我的一些代码。我想知道是否存在定义某个类(3d 向量)的功能,并且可以定义此类的数组(或列表?)。我希望能够在这个数组上使用切片操作。

例如,MATLAB 有这个功能:

obj = class(s,'class_name') 

使用struct s 作为模式创建一个类class_name 对象数组以确定obj 的大小。

我了解 numpy 提供了数组操作所需的一切。我现在正在努力学习,这只是一个例子。所以,我想在没有 numpy 数组的情况下做到这一点。

我以这种方式接近它可能是完全错误的,所以如果有更好的方法可以做到这一点,请随时提出建议。我正在研究子类化 ndarray,但这似乎我只是再次创建一个数组。非常感谢任何建议。

到目前为止我的代码:

class vector3d(object):

    def __init__(self,*args):
        nargs = len(args);
        if(nargs == 0): # Null Vector
            self.x = None; self.y = None; self.z = None;
        elif(nargs==1):
            if (type(args[0]) is vector3d):
                self = args[0];
            elif(type(args[0]) is np.ndarray):
                Vec = args[0];
                if (np.shape(Vec)[0]==1 or np.shape(Vec)[1]==1):
                    if (np.shape(Vec) == (3,1)):
                        self.x = Vec[0,0]; self.y = Vec[1,0]; 
                        self.z = Vec[2,0];

                    elif (np.shape(Vec) == (1,3)):
                        self.x = Vec[0,0]; self.y = Vec[0,1]; 
                        self.z = Vec[0,2];
                    else:
                        raise Exception('Wrong Type of Inputs');
                else:
                    raise Exception('Wrong Type of Inputs');

VecArray = np.ndarray((10,), dtype=np.object);
print np.shape(VecArray);
for i in range(10):
    print i;
    VecArray[i] = vector3d(np.random.rand(3,1));

运行代码后,当我尝试以下操作时:

>>> VecArray[1].x

>>> 0.36923808713820772

>>> VecArray[1:5].x

AttributeError                            Traceback (most recent call last)
<ipython-input-92-899463ad0461> in <module>()
----> 1 VecArray[1:5].x

AttributeError: 'numpy.ndarray' object has no attribute 'x'

我知道我可以列出对象。我应该更具体。我想得到一个可索引的变量作为输出。例如,没有将上述内容视为错误的内容。

【问题讨论】:

  • 您可以将任何您想要的内容放入常规 Python 列表中,包括您的自定义类的实例。
  • 你有没有尝试过什么?
  • @timgeb:所以我只是定义一个类并列出该类?如果我想将 numpy 数组作为输入传递给类怎么办?理想情况下,我希望它输出类的列表(或数组)。例如,如果我输入 numpy 3X10 浮点数组。我想要一个包含 10 个 vector3d 对象的列表。这可以在类的定义中完成吗?
  • @Lidtke:是的,我尝试过自己定义类。我一直在试图弄清楚如何处理数组输入。正如我已经提到的,我也在尝试继承 ndarray。但这只是最终创建了另一个 vector3d 类型的数组。
  • 它(最终)是有道理的,但我认为它(很容易)不可能——切片返回一个容器,该容器与内部对象的属性不同。您也许可以创建一些自定义容器来实现 __getattr__ 并检查其内容以查找它本身没有的任何属性,但这是很多工作。

标签: python arrays class numpy


【解决方案1】:

您可以使用 numpy 数据类型: http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html

>>> dt = np.dtype([('x', np.int32), ('y', np.int32), ('z', np.int32)])
>>> x = np.array([(1, 2, 3), (3, 2, 1)], dtype = dt)
>>> print x 
[(1, 2, 3) (3, 2, 1)]
>>> print x['x'], x['y'], x['z']
[1 3] [2 2] [3 1]
>>> print x[0]['x']
1

扩展示例以添加一些 numpy/matlab 索引:

>>> x = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)], dtype = dt)
>>> print x[1:]['x']
[4 7]

您可以注意到它省略了 X 轴上的第一个元素(1


编辑添加一些关于如何使用自定义数据类型进行子类化的信息。使用来自类似问题https://stackoverflow.com/a/5154869/764322 的答案中的示例并仔细修改它:

>>> class Data(np.ndarray):
        def __new__(cls, inputarr):
            dt = np.dtype([('x', np.int32), ('y', np.int32), ('z', np.int32)])
            obj = np.asarray(inputarr, dtype = dt).view(cls)
            return obj

        def remove_some(self, col, val):
            return self[self[col] != val]

>>> a = Data([(1,2,3), (4,5,6), (7,8,9)])
>>> print a
[(1, 2, 3) (4, 5, 6) (7, 8, 9)]
>>> print a.remove_some('x', 4)
[(1, 2, 3) (7, 8, 9)]

【讨论】:

  • 完美.. 非常感谢!这正是我想要的!我想,如果我没记错的话,你在这里定义了一个数据类型。是否可以将其扩展到一个类?我想为这个类定义一些方法。谢谢! (PS:我会赞成你的回答,但对我的问题的所有反对票最终都会将我的分数降低到 15 分以下!对不起。)
  • 如果我没记错的话,这可能就是你想要的:docs.scipy.org/doc/numpy/user/…。您可以强制 numpy 数组为 dt 的类型,然后添加新方法。
  • 哦,好吧!看起来子类化是要走的路。谢谢!
  • 我刚刚编辑给你一个如何子类化的例子。注意 new 方法中的自定义数据类型。
  • 太好了...非常感谢。这很有帮助。
【解决方案2】:

我想你想要的是numpy.empty:

>>> import numpy as np
>>> a = np.empty((2, 2), dtype=np.object_)
>>> a
array([[None, None],
       [None, None]], dtype=object)

这将创建一个空数组,其中包含指定的 shape(在本例中为 2x2)和 dtype(在本例中为通用对象)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多