Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何创建可以向类添加多个方法的类装饰器?_Python_Python 2.7_Decorator_Python Decorators - Fatal编程技术网

Python 如何创建可以向类添加多个方法的类装饰器?

Python 如何创建可以向类添加多个方法的类装饰器?,python,python-2.7,decorator,python-decorators,Python,Python 2.7,Decorator,Python Decorators,我目前正在尝试实现一个类装饰器,它可以根据参数添加多个方法。例如: @decorator('my_func') class Screen: ... 将向测试类添加方法“my_func”(函数体在decorator中定义) @decorator('my_func', 'my_func2') class Screen: ... 将添加方法“my_func”和“my_func2”。到目前为止,我已经做到了以下几点: def decorator(*args): def wrap

我目前正在尝试实现一个类装饰器,它可以根据参数添加多个方法。例如:

@decorator('my_func')
class Screen:
    ...
将向测试类添加方法“my_func”(函数体在decorator中定义)

@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:
    ...
我在这里的目标是使用这个装饰器,而不必求助于链接,当您有很多参数要传递时,链接可能会很蹩脚


欢迎任何意见

感谢提供的评论,我能够解决我的问题。正如@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

您正在为每个函数创建一个闭包,这意味着无论何时调用函数,而不是创建函数时,
arg
都会被取消引用。此时,
arg
已绑定到循环中的最后一个值。您可以通过
def clicker(self,arg=arg)修复此问题:
您可以使用多重继承和add方法