Abhirath Mahipal Abhirath Mahipal - 5 months ago 11
Python Question

Why am I getting multiple outputs with this decorated function?

I've recently made a move from C/C++ to Python. Having difficulties in understanding closures and decorators.

Declared the functions as such (an online blog had this piece code as an example)

def outer(some_func):
def inner():
print "Before Foo"
ret = some_func()
return ret + 1

return inner

def foo():
return 1


When I run the following code once

foo = outer(foo)
foo()


I get the expected output as

Before Foo
2


However if I run it more than once, I get strange output. I do not understand what happens.

# Writing it down twice instead of running the same cell
# twice on my IPython notebook to better explain things here
foo = outer(foo)
foo = outer(foo)
foo()


The output is as follows

Before Foo
Before Foo
3


Why do I get 3 as the output and why does "Before Foo" get printed twice?

Edit:- What happens when I decorate the function again? Running foo = outer(foo) is quite clear now. What happens when I run foo = outer(foo) again?

Answer

You're decorating the decorated function again. outer takes in a function and returns closure which of course is function by itself. There's nothing preventing you to pass the returned function as a parameter to the following call like you're doing in your example.

If you change your code to print the function being called and return value it's easier to understand what's going on:

def outer(some_func):
    def inner():
        print "Before inner, func: {0}".format(some_func)
        ret = some_func()
        print "After inner, return: {0}".format(ret + 1)
        return ret + 1

    return inner

def foo():
    return 1

foo = outer(foo)
foo = outer(foo)
foo()

Output:

Before inner, func: <function inner at 0x7f1924b516e0>
Before inner, func: <function foo at 0x7f1924b51668>
After inner, return: 2
After inner, return: 3
Comments