2013-06-03 2 views
3

У меня есть класс в python, который выступает в качестве front-end для c-библиотеки. Эта библиотека выполняет симуляции и обрабатывает очень большие массивы данных. Эта библиотека передает массив ctype, и моя обертка преобразует его в правильный numpy.ndarray.Как реализовать массив-оболочку свойств в python?

class SomeClass(object): 
    @property 
    def arr(self): 
     return numpy.array(self._lib.get_arr()) 

Однако для того, чтобы убедиться в том, что проблемы с памятью не происходит, я держать ndarray данные отдельно от данных библиотеки, поэтому изменение ndarray не вызывает изменения в подлинном массиве используется библиотека. Тем не менее, я могу передать новый массив той же формы и перезаписать хранящийся массив библиотеки.

@arr.setter 
def arr(self, new_arr): 
    self._lib.set_arr(new_arr.ctypes) 

Таким образом, я могу взаимодействовать с массивом как так:

x = SomeClass() 
a = x.arr 
a[0] += 1 
x.arr = a 

Мое желание упростить это еще больше, позволяя синтаксис просто x.arr[0] += 1, который был бы более удобным для чтения и имеют меньше переменных , Я не совсем точно знаю, как создать такую ​​оболочку (у меня очень мало опыта в создании классов/функций оболочки), который имитирует свойства, но позволяет доступ к элементу в качестве моего примера.

Как я могу сделать такой класс обертки? Есть ли лучший способ достичь этой цели? Если у вас есть какие-либо советы или чтение, которые могли бы помочь, я был бы очень признателен.

ответ

3

Это может работать. Array является прокси для массива Numpy/C:

class Array(object): 

    def __init__(self): 
     #self.__lib = ... 
     self.np_array = numpy.array(self._lib.get_arr()) 

    def __getitem__(self, key): 
     self.np_array = numpy.array(self._lib.get_arr()) 
     return self.np_array.__getitem__(key) 

    def __setitem__(self, key, value): 
     self.np_array.__setitem__(key, value) 
     self._lib.set_arr(new_arr.ctypes) 

    def __getattr__(self, name): 
     """Delegate to NumPy array.""" 
     try: 
      return getattr(self.np_array, name) 
     except AttributeError: 
      raise AttributeError(
       "'Array' object has no attribute {}".format(name)) 

должны вести себя так:

>>> a = Array() 
>>> a[1] 
1 
>>> a[1] = 10 
>>> a[1] 
10 

10 должен закончиться в массиве C тоже.

+0

Да, я думаю, что в конце концов это может сработать. Я попытался сделать такой класс, но проблема с этим методом заключается в том, что вы теряете все преимущества наличия ndarray. Например, 'a.shape' не будет работать, потому что вам действительно нужно' a.np_array.shape'. Я попытался наследовать от 'numpy.ndarray', но мои попытки не удались. Вы знаете, как можно это сделать? – scicalculator

+0

Добавлен код делегирования. Теперь 'a.shape' должен предоставить' a.np_array.shape'. –

+0

Конечно, перенаправление '__getattr__' именно то, что я должен был делать ¥. Большое спасибо за идеи! – scicalculator

0

Я думаю, что ваш дескриптор должен вернуть экземпляр из списка, как класс, который знает о self._lib и обновлять его во время нормальной работы append, __setitem__, __getitem__ и т.д.

+0

Я думаю, что вы правы, это должна быть оболочка, которая возвращает обернутый массив, как идея Малера, но с добавлением знания о том, что используется lib. Спасибо за совет. – scicalculator

+0

Ну '__setitem__' обновляет массив NumPy и C' _lib'. Массивы NumPy не поддерживают 'append', так как фиксированный размер. –

Смежные вопросы