在装饰函数时,您可以使用方法@object.method
,并且可以使用属性的方法等@object.attribute.attribute.method
。您还可以将额外的参数传递给装饰器@function(foo="bar")
。
然而,看来这些冲突。当链中有一个函数调用时,python似乎认为它是将参数传递给装饰器的位,并且之后的任何链都是SyntaxError。
这里有什么我想念的吗?这种行为或解决方法的原因是什么?
此代码是为Python 3.4编写的。
#!/usr/bin/env python3
class Decorator:
def decorate(self, callback):
return callback
_dec = Decorator()
def findit():
return _dec
class B: dec = _dec
class A: bar = B()
foo = A()
dec = findit()
@dec.decorate
#@findit().decorate
#Above line is a syntax error
@foo.bar.dec.decorate #also permitted
def function():
pass
错误:
File "test.py", line 17
@findit().decorate
^
SyntaxError: invalid syntax
答案 0 :(得分:2)
您已在问题中找到解决方法。在将其作为装饰器应用之前,请先评估findit()
:
dec = findit()
@dec.decorate
def function():
pass
请记住,@decorator
语法只是语法糖,所以上面的内容相当于:
def function():
pass
function = findit().decorate(function)
答案 1 :(得分:2)
The grammar类似于:
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
decorated: decorators (classdef | funcdef | async_funcdef)
此处dotted_name
是(AKA foo
,foo.bar.spam
等):
dotted_name: NAME ('.' NAME)*
从语法中可以清楚地看出,括号后面只能跟一个换行符而不是另一个dotted_name
,因此会引发语法错误。
因此,要解决这个问题,请确保函数调用始终在最后,如果之间存在函数调用,则必须事先将其分配给变量(仅从代码中获取):
dec = findit()
@dec.decorate
有关装饰器语法的历史记录,您可以浏览此文档:https://wiki.python.org/moin/PythonDecorators