Adding and modifying methods at run-time

T

Thomas Weholt

Hi,

I want to add methods to a class instance at run-time based on a base
method, but modify one of the existing ( or add if possible ) params of the
base method. Say a class like this :


class A:
def __init__(self):
self.obj1() # some dummy object having a name attribute
self.obj2() # some dummy object having a name attribute
def __method1__(self, param1, param2, param3 = None):
# use some property on param3 in some operations
def addNewMethod(self, param1, new_obj):
new_func = copy.copy(self.__method1__)
# modify a copy of self.__method1__ and change the param3 to point
new_obj
# and add the method
setattr(self, 'method4%s' % new_obj.name, new_func)

use the class like so :

a = A()
a.addNewMethod(1, a.obj1)
# use new dynamically method
a.method4obj1(1,2) # now the third param with a default is set to point to
obj1 instead of None

I'm crashing at the copy-method in addNewMethod. It crashes with the
exception "TypeError: function() takes at least 2 arguments (0 given)". This
is deep inside the copy-module.

Any hints or clues?

Best regards,
Thomas
 
D

Diez B. Roggisch

Thomas said:
a = A()
a.addNewMethod(1, a.obj1)
# use new dynamically method
a.method4obj1(1,2) # now the third param with a default is set to point to
obj1 instead of None

I'm crashing at the copy-method in addNewMethod. It crashes with the
exception "TypeError: function() takes at least 2 arguments (0 given)".
This is deep inside the copy-module.

Any hints or clues?

I have to admit that I'm not fully undestanding what your code above is
supposed to do - but form what I understand you try to introduce a new
method on an object where a certain named parameter is bound to a special
value.

Now this problem can be split into two parts:

1 - create a method that has a paramter bound to a certain value
2 - add that method to an object instance

The first thing is known as currying, and there is a cookbook recipe that
does that very well:

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549

You will end up with a new method that can be invoked. Now to make this an
instance method, remove the space between the last two words before the
comma in this sentence and look up the result in the python docs :)

Seriously, all you need is the function instancemethod from the module new.
Use it to create a new method on your instance.

The following program illustrates the concepts, the curry-fun is taken from
the recipes comments:

import new

def curry(*args, **create_time_kwds):
func = args[0]
create_time_args = args[1:]
def curried_function(*call_time_args, **call_time_kwds):
args = create_time_args + call_time_args
kwds = create_time_kwds.copy()
kwds.update(call_time_kwds)
return func(*args, **kwds)
return curried_function


class foo:
def method(_, arg1, named_arg=None):
print (arg1, named_arg)

f = foo()

f.method(1)

new_m = curry(foo.method, named_arg="something")

new_m(f,2)

f.new_m = new.instancemethod(new_m, f, foo)

f.new_m(3)
 
T

Thomas Weholt

That worked great !!! Thanks alot.

Thomas


Diez B. Roggisch said:
Thomas said:
a = A()
a.addNewMethod(1, a.obj1)
# use new dynamically method
a.method4obj1(1,2) # now the third param with a default is set to point to
obj1 instead of None

I'm crashing at the copy-method in addNewMethod. It crashes with the
exception "TypeError: function() takes at least 2 arguments (0 given)".
This is deep inside the copy-module.

Any hints or clues?

I have to admit that I'm not fully undestanding what your code above is
supposed to do - but form what I understand you try to introduce a new
method on an object where a certain named parameter is bound to a special
value.

Now this problem can be split into two parts:

1 - create a method that has a paramter bound to a certain value
2 - add that method to an object instance

The first thing is known as currying, and there is a cookbook recipe that
does that very well:

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549

You will end up with a new method that can be invoked. Now to make this an
instance method, remove the space between the last two words before the
comma in this sentence and look up the result in the python docs :)

Seriously, all you need is the function instancemethod from the module new.
Use it to create a new method on your instance.

The following program illustrates the concepts, the curry-fun is taken from
the recipes comments:

import new

def curry(*args, **create_time_kwds):
func = args[0]
create_time_args = args[1:]
def curried_function(*call_time_args, **call_time_kwds):
args = create_time_args + call_time_args
kwds = create_time_kwds.copy()
kwds.update(call_time_kwds)
return func(*args, **kwds)
return curried_function


class foo:
def method(_, arg1, named_arg=None):
print (arg1, named_arg)

f = foo()

f.method(1)

new_m = curry(foo.method, named_arg="something")

new_m(f,2)

f.new_m = new.instancemethod(new_m, f, foo)

f.new_m(3)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top