1
def c(f):
    def inner(*args, **kargs):
        inner.co += 1
        return f(*args, **kargs)
    inner.co = 0
    return inner
@c
def fnc():
    pass
if __name__ == '__main__':
    fnc()
    fnc()
    fnc()
    print(fnc.co)

please explain the final output: 3 I am aware of the functionality of decorators but I'm still not getting the output.

baduker
  • 19,152
  • 9
  • 33
  • 56
Shivam
  • 5
  • 1

2 Answers2

4

First, let's unpack what the decorator syntax does. When you write this:

@c
def fnc():
    pass

… it's equivalent to this:

def fnc():
    pass
fnc = c(fnc)

Now look at what c does: It creates a new function, named inner, and sets inner.co to 0, and returns inner to be used in place of fnc. So, now your code is equivalent to this:

def fnc():
    pass
def inner(*args, **kargs):
    inner.co += 1
    return fnc(*args, **kargs)
inner.co = 0
fnc = inner

So, when you call fnc() three times, you're calling inner each time. So it increments inner.co three times. And since inner and fnc are the same thing, inner.co and fnc.co are the same thing. So print(fnc.co) prints 3.

abarnert
  • 354,177
  • 51
  • 601
  • 671
0

In python, functions are "first class objects" (See What are "first class" objects?). This means you can set attributes on them. You define your function fnc here, and the decorator c adds a property to that function object fnc.co. Its a little weird that the inner.co = 0 initialization is done after the wrapping function is declared, but since inner won't get called until after the co property is defined it doesn't matter. Then in inner the co property gets incremented each time the function is called.

avigil
  • 2,218
  • 11
  • 18
  • still didnt get you,how printing ' fnc.co ' is giving us 3,As each time we are calling c(f) inner.co is initialized to 0 – Shivam Mar 30 '18 at 06:46
  • c only gets run once. `inner()` is what is being called 3 times – avigil Mar 30 '18 at 06:53
  • How is it weird that the `inner.co = 0` is done after the function is declared? When else could you do it? Before the function is declared, there is no function to set attributes on; you'd just get an `UnboundLocalError`. – abarnert Mar 30 '18 at 06:54