2015-02-26 2 views
1

Я пытаюсь добавить новые методы динамически в питоне в конструкторе ...Как создать методы динамически в Python (имя + код)

Контекстного

Я написал модуль Python в C++, который взаимодействует с мои библиотеки обработки сигналов, написанные на C ... У меня есть общий метод доступа к моим модулям (так называемые фильтры).

Например .:

int my_filter_set(void * filter_handle, const char * method_id, void * p_arg); 

Так что мой CPython оборачивает это так:

filter.set(method_id,value) 

И у меня есть доступ ко всем моим метод идентификаторами.

>>> filter.setters 
['SampleRate','...'] 

Цель

Я хотел бы генерировать сеттеры, как:

>>> filter.setSampleRate(value) 

в производном классе.

class Filter(BaseFilter): 
''' 
classdocs 
''' 

def __init__(self, name, library): 
    ''' 
    Constructor 
    ''' 
    BaseFilter.__init__(self,name,library) 

    for setter_id in self.setters: 
     code = 'self.set(' + setter_id + ',value)' 
     # @todo add the method body to a new method called 'set' + method_id (with 'value' as argument) 

Вопросы есть ...

  • Возможно ли это?
  • С модулем типов python?
  • Как это сделать?

Я уже проверил this но я не вижу, как я могу адаптировать его к моей цели.

Спасибо.

ответ

2

Вместо того чтобы создавать методы динамически, вы можете проверить имена методов, которые соответствуют вашему setters, а затем отправке динамически ваш метод set(). Это может быть достигнуто путем переопределения __getattribute__() в вашем Filter классе:

class BaseFilter(object): 
    setters = ('SampleRate', 'Gain', 'BitDepth',) 

    def set(self, method_id, value): 
     print 'BaseFilter.set(): setting {} to {}'.format(method_id, value) 

class Filter(BaseFilter): 
    def __getattribute__(self, name): 
     method_id = name.lstrip('set') 
     if name.startswith('set') and method_id in super(Filter, self).setters: 
      def _set(value): 
       return self.set(method_id, value) 
      return _set 
     else: 
      return super(Filter, self).__getattribute__(name) 

Здесь для методов, которые должны быть отправлены в BaseFilter.set(), __getattribute__() возвращает обернутый версия BaseFilter.set(), которая имеет доступ к method_id в закрытии.


>>> f = Filter() 
>>> f.setSampleRate(44000) 
BaseFilter.set(): setting SampleRate to 44000 
>>> f.setBitDepth(16) 
BaseFilter.set(): setting BitDepth to 16 
>>> f.setGain(100) 
BaseFilter.set(): setting Gain to 100 

>>> f.setHouseOnFire(999) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 9, in __getattribute__ 
AttributeError: 'Filter' object has no attribute 'setHouseOnFire' 
+0

Именно то, что мне нужно, спасибо! –

+0

@GarciaSylvain: отлично. Я тоже был этому доволен! – mhawke

0

Я не уверен, что имена методов вашего сеттера доступны до того, как определение класса впервые встречается, если это так, использование метакласса для создания класса может быть уместным. Если они доступны только во время выполнения, то этот ответ должен указывать путь к вашему решению: Adding a Method to an Existing Object Instance

0

Из вашего описания Я не могу сказать, ищете ли вы способ создания функций Python во время выполнения или вы ищете для пути к provide Python bindings for your existing code base. Существует много способов сделать ваш код доступным для программистов Python.

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