0

Going through functions for the first time (with no technical coding background) i fail to understand a concept, which goes like this.

A simple function factory:

To illustrate this in simple terms, consider the following function, typed at the interactive prompt:

>>> def maker(N):
...     def action(X): # Make and return action
...         return X ** N # action retains N from enclosing scope
...     return action

This defines an outer function that simply generates and returns a nested function, without calling it—maker makes action, but simply returns action without running it. If we call the outer function:

>>> f = maker(2) # Pass 2 to argument N
>>> f

.action at 0x0000000002A4A158>

what we get back is a reference to the generated nested function—the one created when the nested def runs. If we now call what we got back from the outer function:

>>> f(3) # Pass 3 to X, N remembers 2: 3 ** 2
9
>>> f(4) # 4 ** 2
16

we invoke the nested function—the one called action within maker. In other words, we’re calling the nested function that maker created and passed back. Perhaps the most unusual part of this, though, is that the nested function remembers integer 2, the value of the variable N in maker, even though maker has returned and exited by the time we call the action. In effect, N from the enclosing local scope is retained as state information attached to the generated action, which is why we get back its argument squared when it is later called. Just as important, if we now call the outer function again, we get back a new nested function with different state information attached. That is, we get the argument cubed instead of squared when calling the new function, but the original still squares as before:

>>> g = maker(3) # g remembers 3, f remembers 2
>>> g(4) # 4 ** 3
64
>>> f(4) # 4 ** 2 

What exactly happens here. Please give me a perspective i could understand.

Right leg
  • 16,080
  • 7
  • 48
  • 81
  • 1
    Please try to improve the title of your question : right now it's very unclear what the question is going to be about. – P. Camilleri Sep 01 '17 at 14:13
  • Your description is correct, that little bit of state is kept with the returned function. This is called a lexical closure, and it is a function that includes the variables in the lexical scope when the function is created, those variables are "closed over" and saved with the function. I am not really sure what your question ultimately is however, are you asking how this is implemented? – Ukko Sep 01 '17 at 14:13
  • See also https://stackoverflow.com/q/21959985/124319 about *modifying* a variable being captured by the closure – coredump Sep 01 '17 at 14:17
  • This is apparently my first time on stack over flow. I welcome your feedbacks. Will improve over – Kapil Kumar Sep 08 '17 at 08:38

1 Answers1

1

action is what we call a closure. It is a combination of a function object, along with an environment that contains values for so-called free variables, which are non-local names used in the body of the function.

In this case, action is a closure over an environment that contains a value for n, which is "inherited" from the call to maker in which action is defined. Note that each call to maker defines a new function object named action. The closure returned by a call to maker consists of this new function and the value of n passed to maker.

In practice, there is little difference between a function and a closure; it behaves exactly like a function, except some of its non-local names take their values from its enclosed environment rather than the global or calling scope.

chepner
  • 497,756
  • 71
  • 530
  • 681