1

I'm trying add new methods dynamically in python in the constructor ...

Context

I wrote a Python module in C++ that interacts with my signal processing libraries written in C ... I have generic method to access my modules (called filters) parameters.

Eg.:

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

So my cpython wraps it like this :

filter.set(method_id,value)

And I have access to all my method ids.

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

Goal

I would like to generate setters like :

>>> filter.setSampleRate(value)

in a derived class.

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)

Questions are ...

  • Is it possible ?
  • With python types module ?
  • How to do it ?

I already checked this but I don't see the way I can adapt it to my purpose.

Thanks.

Garcia Sylvain
  • 356
  • 4
  • 10

3 Answers3

3

Rather than create the methods dynamically, you can check for method names that match your setters and then dispatch dynamically to your set() method. This can be achieved by overriding __getattribute__() in your Filter class:

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)

Here, for methods that are to be dispatched to BaseFilter.set(), __getattribute__() returns a wrapped version of BaseFilter.set() that has access to the method_id in a closure.


>>> 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'
mhawke
  • 84,695
  • 9
  • 117
  • 138
0

I'm not sure if your setter method names are available before the class definition is first encountered, if so, using a meta class to create the class might be appropriate. If they're only available at runtime, then this answer should direct you the way to your solution: Adding a Method to an Existing Object Instance

Community
  • 1
  • 1
deadbeef404
  • 623
  • 4
  • 14
0

From your description I cannot tell whether you looking for a way to create Python functions at run time or you're looking for a way to provide Python bindings for your existing code base. There are many ways to make your code available to Python programmers.

John Schmitt
  • 1,148
  • 17
  • 39