Chen Lizi
Chen Lizi

Reputation: 103

Closure and Decorator

I just discovered that decorator is one way of nesting functions and I came across this peculiar case with a concept called "closure". It basically means the nested function has access to the outter scope of an enclosing function. This looks intuitive enough till I found this piece of code as follows,

def decorator_with_arguments(function):
   "this decorator actually takes a real function as input"
    def wrapper_accepting_arguments(arg1,arg2):
        print("My arguments are: {0},{1}".format(arg1,arg2))
        function(arg1,arg2)
    return wrapper_accepting_arguments

@decorator_with_arguments
def cities(city_one,city_two):
    print("Cities I love are {0} and {1}".format(city_one,city_two))
cities("Beijing","Chicago")

The output would be as follows,

My arguments are: Bejing,Chicago
Cities I love are Bejing and Chicago

I have two questions regarding this piece of code. First of all, isn't it amazing that the function wrapper_accepting_arguments understands that the arg1 and arg2 come from the function and print them off in a certain way before it has access to the function(arg1,arg2)? Does Python interpreter not read line by line? I understand when you apply multiple decorators to a function, say you have two @ along with a function, then the @ at the bottom gets excuted first. But within the body of a function, why it is read backwards?

The second question is that, if you delete the line of function(arg1,arg2) (as I tried to understand what it does), the output would be as follows,

My arguments are: Beijing,Chicago

as if you had never called the function of "cities" defined at the bottom. why is that?

This along with recursion works in a miraculous way. It's certainly not linear or from top down.

Thank you very much! Any pointer would be really appreciated!

Upvotes: 0

Views: 55

Answers (1)

Glenn D.J.
Glenn D.J.

Reputation: 1965

The moment this code

@decorator_with_arguments
def cities(city_one,city_two):
    print("Cities I love are {0} and {1}".format(city_one,city_two))

gets imported, the function decorator_with_arguments is called with the function cities as parameter. This will immediately return your inner function wrapper_accepting_arguments, which will effectively replace the definition of def cities.

So when you then call cities("Beijing","Chicago"), it is actually calling that inner function wrapper_accepting_arguments with the arguments "Beijing","Chicago". This will cause My arguments are: Beijing,Chicago to be outputted followed by a call to the original definition of the cities (which was saved in the closure) resulting in Cities I love are Beijing and Chicago being printed.

Upvotes: 1

Related Questions