简体   繁体   English

Python - 无法通过使用多个装饰器设置多个属性

[英]Python - Unable to set multiple attributes from utilizing multiple decorators

I am utilizing multiple decorators on a flask API route and I am setting attributes within those decorators (functools wraps), however I am only able to set attributes from within the first decorator that is being called.我在 flask API 路由上使用了多个装饰器,并且我在这些装饰器(functools wraps)中设置属性,但是我只能从被调用的第一个装饰器中设置属性。 I would like to have the ability to set and reference attributes from all decorators being called.我希望能够设置和引用所有被调用的装饰器的属性。

decorators.py装饰器.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

Flask Route: Flask 路线:

@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

Error message from stack trace:来自堆栈跟踪的错误消息:

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

You can move the setattr after the def , so that you're assigning the attribute on the decorated function that you just defined (and that you'll be returning), like this:您可以将setattr移到def之后,以便在您刚刚定义(并且您将返回)的decorated function 上分配属性,如下所示:

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

I've tested (outside of flask), this works for me.我已经测试过(在烧瓶外),这对我有用。

But of course, this begs the question: why do I need decorated and @wraps?但是当然,这引出了一个问题:为什么我需要decorated和@wraps? Well, I'm not sure you do, this also works for me (again, without flask):好吧,我不确定你是否这样做,这也适用于我(同样,没有烧瓶):

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()

(Note that I've simplified the setattr call) (请注意,我已经简化了setattr调用)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM