【问题标题】:Numpy arrays and python propertiesNumpy 数组和 python 属性
【发布时间】:2012-09-11 14:12:41
【问题描述】:

我想在每次设置 numpy 数组时对其内容进行检查。可以为此使用python属性吗?我的做法:

import numpy as np

class Obj(): 
    def __init__(self):                                                                                 
        self._np_arr = None                                                                             

    @property                                                                                           
    def np_arr(self):                                                                                   
        if self._np_arr is None:                                                                        
            self._np_arr = np.ones(10)                                                                  
        return self._np_arr                                                                             

    @np_arr.setter
    def np_arr(self, value):
        if np.sum(value)>10:
            raise ValueError('Error message')                                                           
        self._np_arr = value

if __name__ == '__main__':
    o = Obj()                                                                                           
    print o.np_arr
    o.np_arr = np.zeros(10) # ok                                                                        
    o.np_arr = np.ones(10)*2 # not ok                                                                   
    print o.np_arr       

当对象仍然是 None 时输入 getter。一旦 np_arr 是一个 numpy 数组,getter 和 setter 就不再工作了。

我做错了什么?

【问题讨论】:

    标签: python properties numpy


    【解决方案1】:

    属性仅适用于新式类 - 将 class Obj(): 更改为 class Obj(object): 会产生预期的输出:

    $ python2 test.py
    [ 1.  1.  1.  1.  1.  1.  1.  1.  1.  1.]
    Traceback (most recent call last):
      File "test.py", line 22, in <module>
        o.np_arr = np.ones(10) * 2
      File "test.py", line 16, in np_arr
        raise ValueError('Error message')
    ValueError: Error message
    

    Obj 是旧式类(Python 2 中的默认值)时,分配给o.np_arr 不会调用setter - 它的行为类似于常规属性分配,并破坏属性。

    【讨论】:

      【解决方案2】:

      首先。这很难(最多,我相信不可能)做对。这里的错误很简单,一定是新的样式类。所以只需将class Obj() 替换为class Obj(object)

      但是,这可能无法解决您的问题,因为用户仍然可以将其分配到位,即:

      o.np_arr[:] = 2
      

      您可以通过使用_np_arr.setflags(write=False) 在某种程度上规避这一点,但用户根本无法使用此类操作。

      编辑: 你也可以继承ndarray,并定义你自己的__array_finalize__来规避它。但是,即使这样,用户也可以执行np.asarray(o.np_arr) 并就地修改它...

      我想您可以提供自己的方法,然后通过在可写的内部工作来“模拟”一个数组。但我怀疑是否存在 100% 万无一失或至少优雅的方法。

      【讨论】:

      • 抱歉来回编辑了一下。如果有一种涵盖几乎所有内容的真正优雅的方式,我自己会对此感兴趣,但我怀疑它适用于缓冲区的事实使它变得困难。顺便提一句。谢谢 pgm :)
      【解决方案3】:

      在使用“_”前缀表示它是私有的同时还定义 get/set 属性以直接以o._np_arr 访问它时存在一些命名冲突。

      如果您希望它真正私有,也许您宁愿定义明确的 get/setter(o.set_arro.get_arr)并邀请用户不要就地修改它。

      【讨论】:

        猜你喜欢
        • 2013-06-01
        • 2021-12-17
        • 2014-06-04
        • 2021-11-24
        • 1970-01-01
        • 2015-03-02
        • 1970-01-01
        • 2020-09-06
        • 1970-01-01
        相关资源
        最近更新 更多