I am trying to dynamically create functions in a class that are associated with names of functions in a module. The new functions must be able to call the original functions in the module. However, in the example code below, it appears there might be a memory/uniqueness issue in which the created functions are being overwritten. I'd like to know how to fix this.
I have a file mymod.py that I will import as a module:
def exec_test0():
print "i am exec_test0"
def exec_test1():
print "i am exec_test1"
and a file test.py with a class definition that needs to read the module:
import mymod as mm
class MyClass():
def __init__(self):
self.l = [fn for fn in dir(mm) if fn.startswith('exec_')]
self.create_method()
def create_method(self):
# i expect this to create new methods with unique properties
# as attributes of an object of this class
for fn_exec in self.l:
# this is the function template
# that i want to call the relevant function from the
# module mymod (mm)
def method(self):
method_to_call = getattr(mm, fn_exec)
method_to_call()
# this should create a new name based on the fn_exec
# and assign method to it
name_def = fn_exec.replace('exec_', 'do_')
setattr(self.__class__, name_def, method)
if __name__ == '__main__':
my_obj = MyClass()
my_obj.do_test0()
my_obj.do_test1()
The output of running test.py is:
i am exec_test1
i am exec_test1
I expect:
i am exec_test0
i am exec_test1
Any help on how to achieve this is greatly appreciated!
Update: the answer is given below, but I'm going to write a brief modification here and an extension for the new functions in the class to accept inputs.
The method create_method() in test.py should be updated as outlined in the accepted answer below:
def create_method(self):
# i expect this to create new methods with unique properties
# as attributes of an object of this class
for fn_exec in self.l:
# this is the function template
# that i want to call the relevant function from the
# module mymod (mm)
# because this run at runtime, it requires a param instead
def method(self, fn=fn_exec):
method_to_call = getattr(mm, fn)
method_to_call()
# this should create a new name based on the fn_exec
# and assign method to it
name_def = fn_exec.replace('exec_', 'do_')
setattr(self.__class__, name_def, method)
Furthermore, if one needs to pass parameters to the new method, such as an input some_input, create_method() would be updated as so:
def create_method(self):
# i expect this to create new methods with unique properties
# as attributes of an object of this class
for fn_exec in self.l:
# this is the function template
# that i want to call the relevant function from the
# module mymod (mm)
# because this run at runtime, it requires a param instead
def method(self, some_input, fn=fn_exec):
method_to_call = getattr(mm, fn)
method_to_call()
print(some_input)
# this should create a new name based on the fn_exec
# and assign method to it
name_def = fn_exec.replace('exec_', 'do_')
setattr(self.__class__, name_def, method)
and the main block may look like:
if __name__ == '__main__':
my_obj = MyClass()
my_obj.do_test0('a')
my_obj.do_test1('b')
which will have the following output:
i am exec_test0
a
i am exec_test1
b