将关键字参数传递给类方法装饰器

pri*_*stc 6 python decorator

我有一个类有一个output()方法,它返回一个matplotlib图实例.我有一个我写的装饰器,它接受了fig实例并将其转换为Django响应对象.

我的装饰师看起来像这样:

class plot_svg(object):
    def __init__(self, view):
        self.view = view

    def __call__(self, *args, **kwargs):
        print args, kwargs
        fig = self.view(*args, **kwargs)
        canvas=FigureCanvas(fig)
        response=HttpResponse(content_type='image/svg+xml')
        canvas.print_svg(response)
        return response
Run Code Online (Sandbox Code Playgroud)

这就是它的使用方式:

def as_avg(self):
    return plot_svg(self.output)()
Run Code Online (Sandbox Code Playgroud)

我这样做而不是使用"@"语法的唯一原因是因为当我使用"@"时:

@plot_svg
def as_svg(self):
    return self.output()
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

as_svg() takes exactly 1 argument (0 given)
Run Code Online (Sandbox Code Playgroud)

我试图通过将其置于"@"语法来"修复"这个问题,但我无法弄清楚如何让它工作.我认为它与self未被传递的地方有关...

Ale*_*lli 5

右:当你用类装饰而不是用函数装饰时,你必须使它成为描述符(__get__至少给它一个方法)以获得"自动自我".最简单的是用函数装饰:

def plot_svg(view):

    def wrapper(*args, **kwargs):
        print args, kwargs
        fig = view(*args, **kwargs)
        canvas = FigureCanvas(fig)
        response = HttpResponse(content_type='image/svg+xml')
        canvas.print_svg(response)
        return response

    return wrapper
Run Code Online (Sandbox Code Playgroud)

背景:函数"成为方法"的原因(当在类中定义并通过attribute-get表示法在其实例上访问时),换句话说,这些函数可以自动得到它们的原因self是它们是描述符 - 函数类型有一个__get__.

类没有__get__方法 - 除非您明确添加一个方法.那么为什么不用功能来装饰,如上例所示呢?这样你就__get__可以自动获得很好的函数 - 正如你所看到的那样嵌套函数"lexical closure"属性根本没有任何问题(事实上,它简化了事情 - 嵌套函数调用view,self.view而不是令人困惑的如果self可能意味着你的装饰者类的一个实例或者你正在装饰它的方法的类的实例......! - ).