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