Edgar Navasardyan
Edgar Navasardyan

Reputation: 4511

Cannot set function attribute inside a decorator

I have a Python code like this:

from functools import wraps

def dec(f): 
    
    @wraps(f)
    def wrapper(*args, **kwargs):
        f.foo = 'foo'
        value = f()
        f.foo = 'foo'
        return value
    return wrapper

@dec
def f():
    print('Hello, f')

f()
print(f.foo)

You can find the ready code here:

The problem with this code is that I end up with AttributeError: 'function' object has no attribute 'foo', although I use wraps decorator from functools which should preserve the attribute scope of the function. Any ideas what the cause of the error is ?

Upvotes: 1

Views: 157

Answers (1)

deceze
deceze

Reputation: 522332

You're setting the attribute on f, but you're returning wrapper and the f in the main scope is that wrapper function object. To illustrate with less confusing names:

def dec(f): 
    @wraps(f)
    def wrapper(*args, **kwargs):
        f.foo = 'foo'  # <-- this is the original bar function
        value = f()
        return value

    return wrapper

@dec
def bar():
    print('Hello, f')

bar()  # <-- this is wrapper()

When you change your code to wrapper.foo = 'foo', it works as expected.

Upvotes: 3

Related Questions