Search code examples
pythonscopepython-decoratorsfunction-objectfunction-attributes

accessing function attributes inside decorators


Is it possible to access function attributes inside a decorator? Consider below piece of code.

def deco(a):
    def wrap():
        print(a.status)
        a()
        print(a.status)



    return wrap


@deco
def fun1():
    fun1.status="bar"


fun1.status="foo"
fun1()

I expected the output to be :

foo
bar

But I get the below error:

Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    fun1()
  File "D:\python_projects\test_suite\func_attribute.py", line 3, in wrap
    print(a.status)
AttributeError: 'function' object has no attribute 'status'

Is there any way to make this work since

def fun1():
    fun1.status="bar"


fun1.status="foo"

a=fun1

print(a.status)
a()
print(a.status)

Outputs:

foo
bar

As expected.


Solution

  • Thanks to the decorator, the global name fun1 is bound to the decoration result, so to the nested wrap() function object. Inside wrap() however, a refers to the original, unwrapped function object.

    So you have two different function objects, and each can have attributes; they are not the same objects. fun1.status is a different attribute from a.status.

    You can access the same object as fun1 in the decorator as wrap:

    print(wrap.status)
    

    Demo:

    >>> def deco(a):
    ...     def wrap():
    ...         print(wrap.status)
    ...         a()
    ...         print(wrap.status)
    ...     return wrap
    ...
    >>> @deco
    ... def fun1():
    ...     fun1.status="bar"
    ...
    >>> fun1.status="foo"
    >>> fun1()
    foo
    bar