我目前正在尝试实现一个类装饰器,它可以根据参数添加多个方法。例如:
@decorator('my_func')
class Screen:
...
将方法'my_func'(函数的主体在装饰器中定义)添加到测试类。
@decorator('my_func', 'my_func2')
class Screen:
...
将添加方法'my_func'和'my_func2'。到目前为止,我已成功完成以下任务:
def decorator(*args):
def wrapper(cls):
if not issubclass(cls, Screen):
raise ValueError("You can't apply this decorator "
"on this class.")
for arg in args:
def clicker(self):
return "Hey !" + arg
setattr(cls, arg, clicker)
return cls
return wrapper
这里的问题是所有定义为'my_func'或'my_func2'的方法指向相同的代码,最后一个定义(在我的示例中为'my_func2'的代码)。 例如:
>>> Screen().my_func()
"Hey ! my_func2"
>>> Screen().my_func2()
"Hey ! my_func2"
我尝试了很多调整,例如使用FunctionType复制方法,使用MethodType绑定,结果始终保持不变。
但是这个代码在装饰器被链接时具有预期的行为:
@decorator('my_func')
@decorator('my_func2')
class Test:
...
我的目标是使用这个装饰器而不采用链接,当你有大量参数传递时可能会很蹩脚
欢迎任何想法!
答案 0 :(得分:1)
感谢所提供的评论,我能够解决我的问题。正如@Martijn Pieters所描述的那样,问题来自于我正在为每个函数创建一个闭包而忽略'arg'的范围,因此它是绑定值的循环的迭代。通过传递'arg'作为参数,我现在可以在我的闭包的内部范围中传递我的参数:
def decorator(*args):
def wrapper(cls):
if not issubclass(cls, Screen):
raise ValueError("You can't apply this decorator "
"on this class.")
for arg in args:
def clicker(self, marg=arg):
return "Hey !" + marg
setattr(cls, arg, clicker)
return cls
return wrapper