我有一个类,它有一个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
这就是它的使用方式:
def as_avg(self):
return plot_svg(self.output)()
我这样做而不是使用“@”语法的唯一原因是因为当我使用“@”时:
@plot_svg
def as_svg(self):
return self.output()
我收到此错误:
as_svg() takes exactly 1 argument (0 given)
我试图通过将其置于“@”语法中来“修复”此问题,但我无法弄清楚如何使其正常工作。我认为它与self
没有被传递到它应该的地方有关...
答案 0 :(得分:6)
正确:当您使用类而不是使用函数进行装饰时,您必须使其成为描述符(至少给它一个__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
背景:函数“成为方法”的原因(在类中定义并通过attribute-get表示法在其实例上访问),换句话说,这些函数可以获得自动self
的原因是它们是描述符 - 函数类型有__get__
。
一个类没有__get__
方法 - 除非您明确添加一个。那么为什么不用功能来装饰,如上例所示呢?通过这种方式,您可以自动获得良好的__get__
函数 - 并且如您所见,嵌套函数“lexical closure”属性根本不会产生任何问题(实际上,它简化了事情 - 嵌套函数调用{{ 1}},而不是view
如果self.view
可能意味着您的装饰器类的实例或者您正在装饰的方法的实例,那么这可能会相当混乱。 ..! - 。)
答案 1 :(得分:1)
好的,似乎有几个问题。
首先,一些语法。你得到“只需一个参数”的错误,因为 你的装饰者@plot_svg期待一个参数(一个视图)。还有其他语法错误。
其次,更重要的是,你想要编写一个函数而不是装饰器。装饰者破坏了您对一个概念的访问权限,只允许您访问组合 概念。你只想要一个像这样的新功能:
def as_svg(an_object):
return django_response(an_object.output())
或者,我误解了你的问题,因为代码示例太少了。