类修改后执行错误的方法

时间:2018-12-06 11:52:09

标签: python

我想在工厂函数中使用修改后的方法创建继承的类。奇怪的是,修改后,执行了错误的方法。 基类可能是这样的:

class StupidClass:
    def func1(self, param1):
        print("you called StupidClass.func1")
        return param1

    def func2(self, param1):
        print("you called StupidClass.func2")
        return 2*param1

现在,为了修改方法,我编写了此函数,该函数返回一个新类,该新类继承了输入类,但修改了这些函数:

from inspect import signature
from functools import update_wrapper
import copy

def modify(cls):
    """
    Modifies the methods of the passed class and returns a new class
    """
    class ModifiedClass(cls):
        pass

    for attribute_name in dir(cls): # Loop over all attributes 
        if "func" in attribute_name: # Select all attributes that have "func" in their name
            attribute = getattr(cls, attribute_name)

            print("modifying method", attribute)
            def temp_meth(inst, param1):
                print("you called ModifiedClass." + attribute_name)
                return attribute(inst, param1)

            setattr(ModifiedClass, attribute_name, temp_meth)
    return ModifiedClass

我跑步时

inst = StupidClass()
inst.func1(1)
inst.func2(1)

我得到了预期的输出:

you called StupidClass.func1
1
you called StupidClass.func2
2

但是当我在修改后的类中执行方法时,它总是调用func2:

ModCls = modify(StupidClass)
mod_inst = ModCls()

mod_inst.func1(1)
mod_inst.func2(1)

输出:

modifying method <function StupidClass.func1 at 0x7fa4c802e6a8>
modifying method <function StupidClass.func2 at 0x7fa4c802e730>
you called ModifiedClass.func2
you called StupidClass.func2
2
you called ModifiedClass.func2
you called StupidClass.func2
2

解决方案 由于Python与其他编程语言不同,不会为for循环创建作用域,因此出现了问题。为了克服这个问题,只需在代码周围创建一个函数:

from inspect import signature
from functools import update_wrapper
import copy

def modify(cls):
    """
    Modifies the methods of the passed class and returns a new class
    """
    class ModifiedClass(cls):
        pass

    for attribute_name in dir(cls): # Loop over all attributes 
        if "func" in attribute_name: # Select all attributes that have "func" in their name
            attribute = getattr(cls, attribute_name)
            def just_to_add_a_scope(ModifiedClass, attribute_name, attribute):
                print("modifying method", attribute)
                def temp_meth(inst, param1):
                    print("you called ModifiedClass." + attribute_name)
                    return attribute(inst, param1)

                setattr(ModifiedClass, attribute_name, temp_meth)
            just_to_add_a_scope(ModifiedClass, attribute_name, attribute)
    return ModifiedClass

0 个答案:

没有答案