Python装饰器@func().attribute语法错误 [英] Python decorator @func().attribute syntax error

查看:94
本文介绍了Python装饰器@func().attribute语法错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在这里找到答案,但是找不到.

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] .

强调我的.

理由是圭多(Guido)认为没有真正的用例允许更多:

因此,虽然很容易将语法更改为@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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆