2012-09-19 2 views
3

numpy 배열의 내용을 설정할 때마다 검사를 수행하고 싶습니다. 파이썬 속성을이 용도로 사용할 수 있습니까? 내 접근 방식 :울퉁불퉁 한 배열과 파이썬 속성

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  

개체가 여전히 없음이면 getter가 입력됩니다. np_arr이 numpy 배열이면 getters와 setters는 더 이상 작동하지 않습니다.

내가 뭘 잘못하고 있니?

답변

3

우선. 이것은 옳은 일을하기가 어렵습니다 (최대, 불가능하다고 생각합니다). 여기서 오류는 아주 간단합니다. 새 스타일 클래스 여야합니다. 따라서 class Obj()class Obj(object)으로 바꿉니다.

o.np_arr[:] = 2 

당신은 _np_arr.setflags(write=False)를 사용하여 해당를 다소 우회 할 수 있지만 다음 사용자가 모두 같은 작업을 사용할 수 없습니다 : 사용자가 여전히 제자리에 할당 할 수 있습니다 즉, 이후

그러나 문제를 해결할 수 없습니다 .

편집 : 당신은 또한 ndarray를 하위 클래스로 만들 수 있으며 자신의 __array_finalize__을 정의하여이를 피할 수 있습니다. 그러나 그 후에도 사용자는 np.asarray(o.np_arr)을 수정하여 그 위치에서 수정할 수 있습니다 ...

필자는 자신 만의 방법을 제공하여 쓰기 가능한 내부적으로 "시뮬레이트"하는 배열을 만들 수 있다고 생각합니다. 그러나 나는 100 % 확실한 방법이 있는지 의심 스럽다.

+0

약간의 편집을 위해 죄송합니다. 거의 모든 것을 다루는 정말 우아한 방법이 있다면이 점에 대해 관심을 가지 겠지만, 버퍼에서 작동한다는 사실은 어렵다고 생각합니다. Btw. 고맙습니다 pgm :) – seberg

3

속성은 새로운 스타일의 클래스에서 제대로 작동 - class Obj(object):class Obj():가 예상되는 출력을 제공 변경 :

$ 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 

Objo.np_arr 아무튼에 할당 옛날 스타일 클래스 (파이썬 2의 기본값)이며, setter를 호출하지 않는다. 이것은 규칙적인 속성 할당과 같이 동작하고 속성을 파괴한다.

0

'_'접두어를 사용하면 이름이 고유하지 않으므로 접두사를 사용하면 get/set 속성을 정의하여 직접 액세스 할 수 있습니다 (o._np_arr).

실제로 비공개가되기를 원한다면 명시 적 get/setter (o.set_arr, o.get_arr)를 정의하고 해당 위치를 수정하지 않도록 사용자를 초대하십시오.