I have the following snippet of code:
def wrapper(func):
    def wrapped(*args, **kwargs):
        func.var = 0
        return func(*args, **kwargs)
    return wrapped
@wrapper
def f_out():
    print(f_out.var)
Could you please explain to me why running f_out() raises:
AttributeError: 'function' object has no attribute 'var'
EDIT
I had to elaborate, as an answer has given me the alternative but this will not work for the situation I want it. Given the following snippet:
def wrapper(func):
    def wrapped(*args, **kwargs):
        func.var = 0
        ret = func(*args, **kwargs)
        print(func.var)
    return wrapped
@wrapper
def f_out():
    f_out.var = 1
f_out()
print(f_out.var)
I get as output:
0
1
Why is this happening?
The correct way is to return the wrapped function and change it before returning it:
def wrapper(func):
    def wrapped(*args, **kwargs):
        return func(*args, **kwargs)
    wrapped.var = 0
    return wrapped
@wrapper
def f_out():
    print(f_out.var)
You correctly get:
print(f_out())
gives
0
The updated snipped changes the var attribute twice:
f_out to 1. But at that moment, the function referenced as f_out is the wrapped function and no longer the original one.So when you later print f_out.var you print the attribute for the wrapped function which is 1.
Here is a slightly modified code demonstrating it:
def wrapper(func):
    def wrapped(*args, **kwargs):
        wrapped.orig = func          # keeps a ref to the original function
        func.var = 0
        ret = func(*args, **kwargs)
        print(func.var)
    return wrapped
@wrapper
def f_out():
    f_out.var = 1
f_out()
print(f_out.var, f_out.orig.var)
It prints
0
1 0
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With