redenigma
redenigma

Reputation: 13

python executing nested functions

I have this piece of code, and i am confused about it's execution:

 def makeInc(x):
     def inc(y):
         return y + x
     return inc

 inc5 = makeInc(5)
 # print inc5 --->  <function inc at 0xb721bdbc>
 inc5(12)
 # print inc5(12) gives 17

So, I am wondering why it makes the sum, x+y, only on the second call of the function inc5(). I know what a closure in python really means, but I am still confused.

I have found that piece of code in this web page: http://ynniv.com/blog/2007/08/closures-in-python.html

Upvotes: 1

Views: 79

Answers (2)

Jan Vlcinsky
Jan Vlcinsky

Reputation: 44092

Here are comments to what is happening.

makeInc is a function, which returns another function. Using closures, the returned function knows about x being set to value as it was true at the moment it was created and returned.

Calling inc2 = makeInc(5) first makes x inside makeInc set to 5, and then creates a function y. This inc function knows that x equals to 5 and will remember it as long as it lives - this is concept of closures (get in your backpack all needed variables in the environment at the moment of birth).

Calling inc5(12) executes inc(12). Inside if this call to inc it adds argument y being 12 to the value of x, which the inc5 remembers is 5, so the sum makes 17.

N.B.: Closures are used naturaly in languages like JavaScript. In Python, closures are available too, but not used so often and some developers are considering them even evil - your question shows very clearly, it is not trivial to understand, what is happening in the code - this goes against "readibility counts" from Zen of Python. Also you can find some surprises related to scope and visibility of variables. In case you do not get exactly what has happened in the code above, do not worry, Python offers many other nice challenging structures, which you will use much more often (list comprehension being one example).

Upvotes: 3

Peter Gibson
Peter Gibson

Reputation: 19544

The other answers explain it well, but here's a line by line breakdown of what happens in your code

 def makeInc(x): # define a function makeInc that takes a variable x

     # when makeInc is executed, define a function "inc" that takes a variable y
     def inc(y):
         # when inc is executed, return the sum (where x is closed in the outer function)
         # note this is not executed when makeInc is called
         return y + x

     # don't call inc yet, just return a reference to the function itself - note there
     # are no parenthesis after inc
     return inc

 inc5 = makeInc(5) # now execute makeInc which returns a reference to the inc function 
                   # with the variable x captured by the closure

 inc5(12) # now call the result of the above which is the only place that we call inc
          # note the parenthesis to designate the function call

 # print inc5(12) gives 17

Central to understanding this is the concept of functions as objects. In Python you can do this:

>>> def test(x):
...     return x + 6
...
>>> test(1) # call test with the argument x = 1
7
>>> a = test # assign the function "test" to a new variable "a" - this is not calling test
>>> a
<function test at 0x101cfbb90> # printing a shows the original function name "test"
>>> a(1) # now call that function again with the same value for x = 1
7

When makeInc is called, it returns a reference to inc within which has a different function signature (taking an argument called y). The fact that they both take a single argument is not relevant.

Upvotes: 2

Related Questions