I'm using functools.partial to create a closure, and using setattr to make is callable from a class instance. The idea here is to create a set of methods at runtime.
#!/usr/bin/python
from functools import partial
class MyClass(object):
    def __init__(self, val):
        self.val = val
    @classmethod
    def generateMethods(self):
        def dummy(conf1, self):
            print "conf1:", conf1
            print "self.val:", self.val
            print
        for s in ('dynamic_1', 'dynamic_2'):
            closed = partial(dummy, s)
            setattr(self, "test_{0}".format(s), closed)
It seems to me that partial would bind the current value of s to dummy's first arg, which would free up self to be passed when this is called from an instance.
It's not working how I'd expect
if __name__ == '__main__':
    # Dynamically create some methods
    MyClass.generateMethods()
    # Create an instance
    x = MyClass('FOO')
    # The dynamically created methods aren't callable from the instance :(
    #x.test_dynamic_1()
    # TypeError: dummy() takes exactly 2 arguments (1 given)
    # .. but these work just fine
    MyClass.test_dynamic_1(x)
    MyClass.test_dynamic_2(x)
Is it possible to dynamically create methods which are closures, but callable from instances of the class?
I think the new functools.partialmethod is for this exact use case.
Straight from the docs:
>>> class Cell(object):
...     def __init__(self):
...         self._alive = False
...     @property
...     def alive(self):
...         return self._alive
...     def set_state(self, state):
...         self._alive = bool(state)
...     set_alive = partialmethod(set_state, True)
...     set_dead = partialmethod(set_state, False)
...
>>> c = Cell()
>>> c.alive
False
>>> c.set_alive()
>>> c.alive
True
                        The issue is that when you're calling them using the instances they are actually not bound methods, i.e they have no knowledge about the instance. Bound methods insert the self to the arguments of the underlying function automatically when called, it is stored in the __self__ attribute of bound method.
So, override __getattribute__ and see if the object being fetched is an instance of partial type or not, if yes, convert it to a bound method using types.MethodType.
Code:
#!/usr/bin/python
from functools import partial
import types
class MyClass(object):
    def __init__(self, val):
        self.val = val
    @classmethod
    def generateMethods(self):
        def dummy(conf1, self): 
            print "conf1:", conf1
            print "self.val:", self.val
            print
        for s in ('dynamic_1', 'dynamic_2'):
            closed = partial(dummy, s)
            setattr(self, "test_{0}".format(s), closed)
    def __getattribute__(self, attr):
        # Here we do have access to the much need instance(self)
        obj = object.__getattribute__(self, attr)
        if isinstance(obj, partial):    
            return types.MethodType(obj, self, type(self))
        else:
            return obj
if __name__ == '__main__':
    MyClass.generateMethods()
    x = MyClass('FOO')
    x.test_dynamic_1()
    x.test_dynamic_2()
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With