动态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)