动态python函数创建覆盖函数def
我试图在类中动态创建与模块中的函数名关联的函数。新函数必须能够调用模块中的原始函数。但是,在下面的示例代码中,似乎存在内存/唯一性问题,其中创建的函数被覆盖。我想知道如何解决这个问题 我有一个将作为模块导入的文件动态python函数创建覆盖函数def,python,Python,我试图在类中动态创建与模块中的函数名关联的函数。新函数必须能够调用模块中的原始函数。但是,在下面的示例代码中,似乎存在内存/唯一性问题,其中创建的函数被覆盖。我想知道如何解决这个问题 我有一个将作为模块导入的文件mymod.py: def exec_test0(): print "i am exec_test0" def exec_test1(): print "i am exec_test1" 以及一个文件test.py,其中包含需要读取模块的类定义: import mym
mymod.py
:
def exec_test0():
print "i am exec_test0"
def exec_test1():
print "i am exec_test1"
以及一个文件test.py
,其中包含需要读取模块的类定义:
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()
运行test.py
的输出为:
i am exec_test1
i am exec_test1
我期望:
i am exec_test0
i am exec_test1
非常感谢您对如何实现这一目标的任何帮助
更新:下面给出了答案,但我将在这里写一个简短的修改,并为类中的新函数编写一个扩展,以接受输入
test.py
中的方法create\u 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)
# 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)
此外,如果需要将参数传递给新方法,例如输入某些输入
,创建方法()
将更新如下:
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)
主块可能看起来像:
if __name__ == '__main__':
my_obj = MyClass()
my_obj.do_test0('a')
my_obj.do_test1('b')
将具有以下输出:
i am exec_test0
a
i am exec_test1
b
在调用method
之前,不会计算fn_exec
主体中的名称fn_exec
,此时fn_exec
具有它在for
循环中接受的最后一个值。要确保在定义方法
时使用其值,您需要使用默认参数值:
def method(self, fn=fn_exec):
method_to_call = getattr(mm, fn)
method_to_call()
当定义了method
时,fn
被设置为等于fn_exec
的当前值,因此这是定义method_to_call
时使用的值。这与Python中闭包的工作方式有关。添加一个方法,例如:
def make_wrapper(self, method_to_call):
def method(self):
method_to_call()
并将create_method()
更改为:
def create_method(self):
for fn_exec in self.l:
method_to_call = getattr(mm, fn_exec)
method = self.make_wrapper(method_to_call)
name_def = fn_exec.replace('exec_', 'do_')
setattr(self.__class__, name_def, method)
由于您是在实例上执行此操作,我建议在实例上设置方法(并绑定到self),而不是直接在类上设置它们:
setattr(self, name_def, method.__get__(self, self.__class__))
# Instead of
setattr(self.__class__, name_def, method)