【问题标题】:Function calls in function decoration函数装饰中的函数调用
【发布时间】:2017-05-23 18:29:01
【问题描述】:

装饰函数时,可以使用@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

【问题讨论】:

  • 试试@(findit().decorate)。可能是优先问题?
  • @(findit().decorate) 在左括号上出现语法错误。

标签: python python-decorators


【解决方案1】:

The grammar 装饰器类似于:

decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
decorated: decorators (classdef | funcdef | async_funcdef)

这里dotted_name 是(又名foofoo.bar.spam 等):

dotted_name: NAME ('.' NAME)*

从语法来看,括号后面只能跟换行符,不能跟dotted_name,因此会抛出语法错误。

因此,要解决此问题,请确保函数调用始终在末尾,如果中间有函数调用,则必须事先将其分配给变量(仅取自您的代码):

dec = findit()
@dec.decorate

有关装饰器语法的历史,您可以查看此文档:https://wiki.python.org/moin/PythonDecorators

【讨论】:

    【解决方案2】:

    您的问题中已经有了解决方法。在将findit() 用作装饰器之前,只需评估它:

    dec = findit()
    @dec.decorate
    def function():
        pass
    

    记住@decorator语法只是语法糖,所以上面的等价于:

    def function():
        pass
    
    function = findit().decorate(function)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-15
      • 2010-09-21
      • 2017-09-13
      • 2017-12-11
      • 1970-01-01
      • 1970-01-01
      • 2020-04-28
      • 2020-03-19
      相关资源
      最近更新 更多