Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decorator is run without being called

I have dived into the Python decorator and was playing around with some ways to add function arguments to decorators.

The problem I am facing has to do with me wanting to do a recursion in the decorator while setting some variables only on the initial call. So in the example I would like to print the message only once on the function call.

Right now it prints on function definition, not on function call. See this example code:

def recursiveCounter(message):
    def decorater(func):
        def wrapper(count):
            func(count)
            if count < 10:
                count += 1
                wrapper(count)

        print message
        return wrapper
    return decorater


@recursiveCounter("hello I was called once")
def counter(count):
    print count


counter(0)

1 Answers

Below I have added comments to indicate when each line runs:

def recursiveCounter(message):  # when the decorator is defined
    def decorater(func):  # when the decorator is created - @recursiveCounter("hello I was called once")
        def wrapper(count):  # when the function is decorated - def counter(count): print count
            func(count)  # when the function is called - counter(0)
            if count < 10:  # when the function is called
                count += 1  # when the function is called 
                wrapper(count)  # when the function is called

        print message  # **when the function is decorated**
        return wrapper  # when the function is decorated
    return decorater  # when the decorator is created

As you can see, the line print message runs when the function gets decorated, not when it gets called. If you want it to run when the function gets called, you should indent it one level further, so it is within wrapper rather than decorater.


If you really want to keep the recursive implementation, rearrange the wrapper to define and call the recursion itself:

...
def wrapper(count):
    def inner_wrapper(count):
        if count < 10:
            inner_wrapper(count + 1)
    inner_wrapper(count)
    print message
like image 197
jonrsharpe Avatar answered Oct 19 '25 08:10

jonrsharpe