This question (not a question on Qiita)
I understand that closures can refer to outer variables, but I'm not convinced. Doesn't the variable [^ 1](including arguments) in the function disappear when the function ends? The variable may be held somewhere, but where is it specifically?
[^ 1]: To be exact, the object referenced by the variable
On the contrary
"First you have to think that's what it is. If you want to know more, you have to read the Python source. By the way, it's tied to a function (closure)."
I answered, but when I thought about it a little more,
"Where did you learn from the concept of variables disappearing when the function ends (although they disappear)? It is assumed that you have no knowledge of language implementation (that is, knowledge that variables are secured on the stack [^ 2])."
[^ 2]: For more information about this area [here](https://qiita.com/junjis0203/items/7d3e63253a3d291a04c6#%E9%96%A2%E6%95%B0%E3%81%AE%E5% AE% 9F% E8% A1% 8C% E6% 96% B9% E6% B3% 95% E3% 83% AD% E3% 83% BC% E3% 82% AB% E3% 83% AB% E5% A4% See also 89% E6% 95% B0)
I was worried about that. That's why this time I will explain the concept around here with pictures.
Before the closure is a normal function first.
Ordinary function
def add(a, b):
return a + b
add(2, 3)
The last line calls ʻadd with ʻa
as 2 and b
as 3. If you draw this in the figure, it will be as follows.
The "execution state of add" is because of the "behavior when the function ends" which will be explained later (the story becomes inaccurate if "add" is used), but anyway, for the object "2". From the execution state, the arrow of ʻa and the arrow of
b` appear for the object "3". Don't worry too much because a and b are upside down to match the figure you will draw later.
ʻWhen add ends, the "add execution state" disappears. Then, of course, the ʻa
and b
arrows that are out of the execution state also disappear. This is the situation where the variable disappears when the function ends.
So far, we have explained "the image of variables when the function is executed" and "the image of variables when the function ends". With this in mind, let's move on to closures. There is a useless b
variable, but it's convenient.
closure
def make_adder(a, b):
def adder(x):
return x + a
return adder
adder3 = make_adder(2, 3)
adder3(4)
When the make_adder (2, 3)
call is made and the time before the return
of the make_adder
(that is, after the ʻadder is defined) is drawn in the figure as follows. In other words, the "2" pointed to by ʻa
is referenced by both make_adder
(execution state) and ʻadder`. [^ 3]
[^ 3]: The arrow from "make_adder execution state" and the one pointed to are ʻadder`, but this is not an error because "the function itself has the name adder".
When make_adder
finishes, the execution state disappears like a normal variable. However, the ʻadder body written in blue has been returned, so it will not disappear. And ʻa
(pointed to" 2 ") referenced by ʻadder` does not disappear either.
In this way, ʻa (the one referenced by) remains, so when ʻadder3 (4)
is called after that, the saved "2" can be retrieved and used.
That's it. Oh, I think nonlocal is a little more annoying, but I haven't checked it, so I'll omit it.
[Python] What is closure (function closure) It describes in detail how variables are stored.
[Read Python / Closure](http://dzeta.jp/~junjis/code_reading/index.php?Python%2F%E3%82%AF%E3%83%AD%E3%83%BC%E3%82 % B8% E3% 83% A3) This is a memo when I read "Details of Closure Implementation" about two and a half years ago.
Recommended Posts