【问题标题】:Python - Unable to set multiple attributes from utilizing multiple decoratorsPython - 无法通过使用多个装饰器来设置多个属性
【发布时间】:2021-05-17 09:42:06
【问题描述】:

我在烧瓶 API 路由上使用多个装饰器,并且我在这些装饰器中设置属性(functools 包装),但是我只能从被调用的第一个装饰器中设置属性。我希望能够设置和引用所有被调用的装饰器的属性。

装饰器.py

from functools import wraps

def example_func1(f):
    @wraps(f)
    def decorated(*args, **kwargs):

        setattr(decorated, 'name', 'bill')

        return f(*args, **kwargs)

    return decorated

    
    def example_func2(f):
        @wraps(f)
        def decorated(*args, **kwargs):

            setattr(decorated, 'cookie', 'chocolate')
    
            return f(*args, **kwargs)
    
        return decorated

    
    def example_func3(f):
        @wraps(f)
        def decorated(*args, **kwargs):

            setattr(decorated, 'shoes', 'nike')
    
            return f(*args, **kwargs)
    
        return decorated

烧瓶路线:

@app.route("/myRoute", methods=["GET", "OPTIONS"])
@example_func1
@example_func2
@example_func3
def my_route():
    print(my_route.name) # this returns 'bill' as expected
    print(my_route.cookie) # stack trace for no attribute
    print(my_route.shoes) # didn't get this far

来自堆栈跟踪的错误消息:

AttributeError: 'function' object has no attribute 'cookie'

【问题讨论】:

  • 你的装饰器在他们的参数上设置属性,而不是函数,他们同样返回一个包装器,而不是函数。

标签: python flask decorator


【解决方案1】:

您可以将setattr 移到def 之后,以便分配 您刚刚定义的 decorated 函数上的属性(并且您将 返回),像这样:

def example_func3(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        return f(*args, **kwargs)
    setattr(decorated, 'shoes', 'nike')
    return decorated

我已经测试过(在烧瓶外),这对我有用。

当然,这引出了一个问题:为什么我需要 decorated 和 @wraps ? 好吧,我不确定你是否这样做,这也适用于我(同样,没有烧瓶):

from functools import wraps

def example_func1(f):
    f.name = 'bill'
    return f

def example_func2(f):
    f.cookie = 'chocolate'
    return f

def example_func3(f):
    f.shoes = 'nike'
    return f

@example_func1
@example_func2
@example_func3
def func():
    print(f'func: name={func.name}')
    print(f'func: cookie={func.cookie}')
    print(f'func: shoes={func.shoes}')

func()

(请注意,我已经简化了 setattr 调用)

【讨论】:

  • 所以问题也出在烧瓶上。每条路由都需要有一个唯一的函数名,所以@wraps 是必要的,因为我有多个路由,这将允许我取回唯一的函数名,否则我会取回装饰器作为函数名并有多个路由,我会不是唯一的错误。
猜你喜欢
  • 2017-07-16
  • 1970-01-01
  • 2013-06-15
  • 2019-09-20
  • 2013-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-08
相关资源
最近更新 更多