Python装饰器@func().attribute语法错误 [英] Python decorator @func().attribute syntax error
问题描述
我试图在这里找到答案,但是找不到.
I tried to find an answer here, but could not.
@obj.func # works
@obj.func(**kwargs) #works
@obj.func1(**kwargs).func2 #-> syntax error
我不明白为什么第三种形式是SyntaxError,对于我来说似乎没有违反任何python语法,而且对于用户而言我很清楚要做什么(请参见下面的示例).
I do not understand why the third form is a SyntaxError, it seems for me that is not violating any python syntax and it is clear for me what the user want to do (see example below).
我查看了装饰器实现的 pep 0318 ,但没有找到任何答案.
I looked at pep 0318 of decorator implementation but didn't find any answers.
以下是使用示例:
class ItemFunc(object):
def __init__(self, fcall=None, **kwargs):
self.defaults = kwargs
self.fcall = None
def __call__(self, *args, **kwargs):
kwargs = dict(self.defaults, **kwargs)
# do something more complex with kwargs
output = self.fcall(*args, **kwargs)
# do something more with output
return output
def caller(self, fcall):
""" set call and return self """
self.call = fcall # after some check obviously
return self
def copy(self,**kwargs):
kwargs = dict(self.defaults, **kwargs)
return self.__class__(self.fcall, **kwargs)
def copy_and_decorate(self, **kwargs):
return self.copy(**kwargs).caller
比起您可以将ItemFunc用作装饰器
Than you can use ItemFunc as a decorator:
@ItemFunc
def plot(**kwargs):
pass
redcross = plot.copy(color="red", marker="+")
@redcross.caller
def plot_data1(**kwargs):
pass
bluecross = redcross.copy(color="blue")
@bluecross.caller
def plot_data2(**kwargs):
pass
但是为什么禁止遵循以下捷径语法":
But why this following 'short cut syntax' is forbidden :
@redcross.copy(color="blue").caller
def plot_data2(**kwargs):
pass
但是我可以做到:
@redcross.copy_and_decorate(color="blue")
def plot_data2(**kwargs):
pass
第一种形式看起来更好,至少我更了解背后的意图.
The first form looks for nicer, at least I understand better the intentions behind.
推荐答案
函数定义语法不允许使用进一步的点分名称进行调用;语法仅限于点分名称和结尾处的可选调用
decorated ::= decorators (classdef | funcdef)
decorators ::= decorator+
decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE
funcdef ::= "def" funcname "(" [parameter_list] ")" ":" suite
dotted_name ::= identifier ("." identifier)*
请注意,这不是一个完整的表达式,而是一个非常有限的子集.
Note that that's not a full expression, but a very limited subset.
这呼应PEP,其中指出:
This echoes the PEP, which states:
decorator语句的接受范围受到限制-任意表达式将不起作用. Guido之所以喜欢这种方式,是因为有一种直觉[17].
The decorator statement is limited in what it can accept -- arbitrary expressions will not work. Guido preferred this because of a gut feeling [17] .
和
具有返回修饰符的函数的理由是,@符号后的部分可以被视为表达式(尽管在语法上仅限于一个函数),以及该表达式返回的内容叫做.参见声明参数[16].
The rationale for having a function that returns a decorator is that the part after the @ sign can be considered to be an expression (though syntactically restricted to just a function), and whatever that expression returns is called. See declaration arguments [16] .
强调我的.
因此,虽然很容易将语法更改为@test, 未来,我想坚持使用更严格的形式,除非真正的 给出了用例,其中允许@test将增加可读性. (@foo().bar()不算在内,因为我不希望您会需要 ).
So while it would be quite easy to change the syntax to @test in the future, I'd like to stick with the more restricted form unless a real use case is presented where allowing @test would increase readability. (@foo().bar() doesn't count because I don't expect you'll ever need that).
您必须说服Guido和其他核心开发人员,您的案例是值得取消这些限制的适当用例!
You'll have to convince Guido and the other core developers that your case is a proper usecase worthy of lifting these restrictions!
这篇关于Python装饰器@func().attribute语法错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!