【问题标题】:Python struct like Matlab类似于 Matlab 的 Python 结构
【发布时间】:2015-12-03 20:01:17
【问题描述】:

我似乎找到了很多 hack 答案,但对这些问题没有“标准化”答案。我正在寻找在 Python 中实现 Matlab 的结构,特别是具有以下两个功能:

  1. 在结构“s”中,使用点表示法访问字段值“a”(即 s.a)
  2. 即时创建字段,无需初始化 dtype、格式(即 s.b = np.array([1,2,3,4]) )

有没有办法在 Python 中做到这一点?迄今为止,我找到的唯一解决方案是here,使用了一个虚拟类 structtype()。这可行,但感觉有点骇人听闻。 我还认为 scipy 可能会暴露它的 mat_struct,在 loadmat() 中使用,但我找不到它的公共接口。 其他人做什么?我不太担心这个结构的性能,它更方便。

【问题讨论】:

  • 为什么需要使用. 表示法?为什么不能只使用dict
  • 不是需要,更多的是偏好。也许我只需要克服它。没有要求 (1),dict 工作正常
  • 一个 dict 将会变得更加容易使用,这要归功于它提供的所有方法。而且它的编写时间会更短,并且会更快地完成大多数(如果不是全部)操作。此外,您将找到的大多数内置和第三方函数和类都旨在与 dicts 一起使用。
  • Matlab 的 struct 基本上是一个 Python dict,(key,value) 对...

标签: python matlab numpy scipy


【解决方案1】:

如果您使用的是 3.3 及更高版本,则有 types.SimpleNamespace。除此之外,空班可能是您最好的选择。

【讨论】:

  • 如果您还没有使用 3.3,那么将示例实现复制到您自己的代码中是一个非常合理的选择。我使用类似的东西。有时,它被称为Bunch,例如在scikit-learn.
【解决方案2】:

最简单和直观最相似的 Python 实现是使用type 来实例化一个临时类。它实际上类似于创建一个虚拟类,但我认为它在语义上更清楚地表达了类似结构的对象的意图。

>>> s = type('', (), {})()
>>> s.a = 4
>>> s.a
4

在这里,type 用于创建一个无名类(因此为''),没有基类(或父类,由空元组表示)和默认类属性(空字典)和最终的()实例化类/结构。请记住,传递给字典的值不会显示在实例的 __dict__ 属性中,但这可能与您无关。此方法也适用于旧版本 (

【讨论】:

    【解决方案3】:

    我在 Octave 中做到了:

    octave:2>      x.a = 1;
    octave:3>      x.b = [1, 2; 3, 4];
    octave:4>      x.c = "string";
    octave:7> save -7 test.mat x
    

    在 ipython (2.7) 中:

    In [27]: from scipy.io import loadmat    
    In [28]: A=loadmat('test.mat')
    
    In [29]: A
    Out[29]: 
    {'__globals__': [],
     '__header__': 'MATLAB 5.0 MAT-file, written by Octave 3.8.2, 2015-12-04 02:57:47 UTC',
     '__version__': '1.0',
     'x': array([[([[1.0]], [[1.0, 2.0], [3.0, 4.0]], [u'string'])]], 
          dtype=[('a', 'O'), ('b', 'O'), ('c', 'O')])}
    

    在这种情况下,A['x'] 是一个 numpy 结构化数组,具有 3 个 dtype=object 字段。

    In [33]: A['x']['b'][0,0]
    Out[33]: 
    array([[ 1.,  2.],
           [ 3.,  4.]])
    
    In [34]: A['x'][0,0]
    Out[34]: ([[1.0]], [[1.0, 2.0], [3.0, 4.0]], [u'string'])
    
    In [35]: A['x'][0,0]['b']
    Out[35]: 
    array([[ 1.,  2.],
           [ 3.,  4.]])
    

    由于 x 来自 MATLAB,我必须使用 [0,0] 对其进行索引。

    octave:9> size(x)
    ans =
       1   1
    

    我可以使用不同的开关加载A,并使用.b 格式访问属性:

    In [62]: A=loadmat('test.mat',struct_as_record=False)
    
    In [63]: A['x'][0,0].b
    Out[63]: 
    array([[ 1.,  2.],
           [ 3.,  4.]])
    

    在这种情况下,A['x'] 的元素是 <scipy.io.matlab.mio5_params.mat_struct at 0x9bed76c> 类型

    一些历史可能会有所帮助。 MATLAB 最初只有二维矩阵。然后他们扩展它以允许更高的维度。 cells 被添加,具有相同的 2d 字符,但允许不同的内容。 structures 已添加,允许“命名”属性。最初的 MATLAB 类系统是建立在结构上的(只需将某些函数链接到特定的类结构)。 MATLAB 现在处于其第二代类系统中。

    Python 从类、字典和列表开始。使用与 MATLAB 结构相同的 . 语法访问对象属性。带键的字典(通常,但不总是字符串)。用整数索引的列表,并且总是允许不同的内容(如cells)。借助成熟的对象类系统,可以在 Python 中构建更精细的数据结构,尽管访问仍然受基本 Python 语法的约束。

    numpy 添加 n 维数组。子类np.matrix 始终是二维的,以旧式 MATLAB 矩阵为模型。数组总是具有相同种类的元素。但是dtype=object 数组包含指向 Python 对象的指针。在许多方面,它们只是带有数组包装器的 Python 列表。它们靠近 MATLAB 单元。

    numpy 也有结构化数组,有一个复合 dtype,由 fields 组成。 fields 按名称访问。 np.recarray 是一个结构化数组,增加了使用 . 语法访问字段的能力。这使它们看起来很像 MATLAB 结构数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-26
      • 1970-01-01
      • 2021-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-25
      相关资源
      最近更新 更多