3

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.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343

1 Answers1

1

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
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • def deco(a): def wrap(): print(fun1.status) a() print(fun1.status) return wrap @deco def fun1(): fun1.status="bar" fun1.status="foo" fun1() – Sudhan Nadar Nov 17 '17 at 10:00
  • @SudhanNadar: yes, because then you are referencing the global `fun1` name that the decorator targeted. But now you are bound to that *one function you decorated*, you can't use the decorator on another function `fun2` and expect to get access to the attributes of that second function object when you call it. `wrap` will always be the right reference to the decoration result. – Martijn Pieters Nov 17 '17 at 10:19