When I was looking at the closure implementation, I didn't know why it worked, so I looked at how the scope looked. I think it's very basic, but I couldn't find an article on the net that I could understand about how the scope looks. As a result of actually moving it, I thought it was difficult to explain.
Let's check the state of global variables and local variables with the following code.
from pprint import pprint
print "-----globals----->>>"
pprint(globals())
print "-----locals----->>>"
pprint(locals())
Execution result
-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes002.py',
'__name__': '__main__',
'__package__': None,
'pprint': <function pprint at 0x02222770>}
-----locals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes002.py',
'__name__': '__main__',
'__package__': None,
'pprint': <function pprint at 0x02222770>}
In this state, the contents displayed for both global variables and local variables are the same. What happens if you define one variable?
from pprint import pprint
a = 123
pprint(globals())
print "-----globals----->>>"
print "-----locals----->>>"
pprint(locals())
Execution result
-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes002.py',
'__name__': '__main__',
'__package__': None,
'a': 123,
'pprint': <function pprint at 0x02222770>}
-----locals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes002.py',
'__name__': '__main__',
'__package__': None,
'a': 123,
'pprint': <function pprint at 0x02222770>}
In the top-level script execution environment, the output contents of locals () and globals () are the same. The defined variables are present in both outputs. (*** It is judged that globals () and locals () are outputting the names of global scope and local scope, respectively, and the following is described **)
Also, pprint is in the output of globals (). (also in locals ()) Modules and functions imported by import will be included in the global scope. (Those that can be directly referenced at the top level are in the global scope)
What happens if you define a function and look at the scope from within the function?
##Verification(3)
a = 123
def tes001():
b = 234
print "-----globals----->>>"
pprint(globals())
print "-----locals----->>>"
pprint(locals())
tes001()
Execution result
-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes002.py',
'__name__': '__main__',
'__package__': None,
'a': 123,
'pprint': <function pprint at 0x02422770>,
'tes001': <function tes001 at 0x02422BF0>}
-----locals----->>>
{'b': 234}
The variable b defined in the function block exists in the local scope but not in the global scope.
Now let's define the variables after displaying the contents of locals () and globals () in the function block.
a = 123
def tes001():
print "-----globals----->>>"
pprint(globals())
print "-----locals----->>>"
pprint(locals())
b = 234
tes001()
Execution result
-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes002.py',
'__name__': '__main__',
'__package__': None,
'a': 123,
'pprint': <function pprint at 0x02222770>,
'tes001': <function tes001 at 0x02222BF0>}
-----locals----->>>
{}
In this case, the variable b is not in the local scope either. What happens if you put the output of locals () before and after the variable definition?
a = 123
def tes001():
print "-----globals----->>>"
pprint(globals())
print "-----locals(1)----->>>"
pprint(locals())
b = 234
print "-----locals(2)----->>>"
pprint(locals())
tes001()
Execution result
-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes002.py',
'__name__': '__main__',
'__package__': None,
'a': 123,
'pprint': <function pprint at 0x02222770>,
'tes001': <function tes001 at 0x02222BF0>}
-----locals(1)----->>>
{}
-----locals(2)----->>>
{'b': 234}
This is as expected. It is not in the output before the variable is defined, but it is in the output after it is defined.
Next, let's nest the definition of the function and check the scope from the inner function.
a = 123
def tes001():
b = 234
def inner():
c = 345
print "-----globals----->>>"
pprint(globals())
print "-----locals----->>>"
pprint(locals())
inner()
tes001()
Execution result
-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes002.py',
'__name__': '__main__',
'__package__': None,
'a': 123,
'pprint': <function pprint at 0x022226F0>,
'tes001': <function tes001 at 0x02222BF0>}
-----locals----->>>
{'c': 345}
There is no b in the local scope of inner (). What happens if you refer to b in inner ()? Display the output of locals () before and after referencing.
a = 123
def tes001():
b = 234
def inner():
c = 345
print "-----globals----->>>"
pprint(globals())
print "-----locals(1)----->>>"
pprint(locals())
print b
print "-----locals(2)----->>>"
pprint(locals())
inner()
tes001()
Execution result
-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes002.py',
'__name__': '__main__',
'__package__': None,
'a': 123,
'pprint': <function pprint at 0x022226F0>,
'tes001': <function tes001 at 0x02222BF0>}
-----locals(1)----->>>
{'b': 234, 'c': 345}
234
-----locals(2)----->>>
{'b': 234, 'c': 345}
This time, the variable b also exists in the local scope before referencing the variable b ( print b
). This looks a little different from "confirmation (5)". The behavior is different between reference and assignment.
Sensorially,
-----locals(1)----->>>
{'c': 345}
234
-----locals(2)----->>>
{'b': 234, 'c': 345}
I thought it would be like this. From the above result, it is assumed that the scope including the variable b is created in the local scope of the inner () function before executing the code. In the first place, the variable b is included in the local scope even though it is undefined in the inner () function. From the viewpoint of movement, when a function is nested, when a variable that is undefined in the inner function and is defined in the outer is referenced by the inner function, the definition contents of the outer function are copied and the inner function is copied. Set to the local scope of. This scope setting seems to be done before code execution. The feeling is that something like the initial value of the local scope is created before the function is executed.
Let's examine the scope when the variable defined on the outside is changed by the function on the inside.
a = 123
def tes001():
b = 234
def inner():
c = 345
print "-----inner: globals----->>>"
pprint(globals())
print "-----inner: locals(1)----->>>"
pprint(locals())
print b
b = 777
print "-----inner: locals(2)----->>>"
pprint(locals())
inner()
print "-----outer: locals(3)----->>>"
pprint(locals())
tes001()
Execution result
-----inner: globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes002.py',
'__name__': '__main__',
'__package__': None,
'a': 123,
'pprint': <function pprint at 0x022226F0>,
'tes001': <function tes001 at 0x02222BF0>}
-----inner: locals(1)----->>>
{'c': 345}
Traceback (most recent call last):
File "tes002.py", line 19, in <module>
tes001()
File "tes002.py", line 16, in tes001
inner()
File "tes002.py", line 12, in inner
print b
UnboundLocalError: local variable 'b' referenced before assignment
After executing the above, I got an error (Unbound Local Error).
Interestingly here, the content of locals (), which is first output by the inner () function, does not include the variable b.
If only the reference ( print b
) was done, b was included. The only difference is whether the inner function sets the variables defined on the outer.
After all, it seems that the scope is prepared before executing the code. The code works based on this prepared scope.
However, in the above sample, since there is a setting code ( b = 777
) in the internal function, the variable b is not set in the local scope prepared at runtime.
In this state (variable b is not in scope), an error occurs when trying to refer to variable b.
If you organize the contents confirmed so far, including some reasoning (speculation),
--In the top-level execution environment, all defined variables and functions are set to the global scope. Variables are defined by assignment. --The same global scope can be seen from both the top level and the function. (Probably) --Variables and functions (internal functions) defined in a function are set in the local scope of that function. -If you refer to an undefined variable in a function, before executing the code, look for the variable defined in the outer function from near the function to the outside, and local scope the found variable. Set to. The function works with this local scope. --However, when assigning to a variable in a function, the variable is defined in the function, and the variable is not set in the local scope at runtime. In this state, if you try to refer to a variable before assignment, an error (UnboundLocalError) will occur.
Next, let's examine how the scope looks when a global variable is referenced and set in a function.
a = 123
def tes001():
print a
print "-----tes001: globals(1)----->>>"
pprint(globals())
print "-----tes001: locals(1)----->>>"
pprint(locals())
a = 345
print "-----tes001: globals(2)----->>>"
pprint(globals())
print "-----tes001: locals(2)----->>>"
pprint(locals())
tes001()
print "-----top: globals(3)----->>>"
pprint(globals())
print "-----top: locals(3)----->>>"
pprint(locals())
Execution result
Traceback (most recent call last):
File "tes003.py", line 15, in <module>
tes001()
File "tes003.py", line 5, in tes001
print a
UnboundLocalError: local variable 'a' referenced before assignment
In this case, the same as confirmation (7). UnboundLocalError. Same behavior when global scope and local scope are mixed. In the function tes001 (), assigning the variable a and then referencing it should work.
a = 123
def tes001():
print "-----tes001: globals(1)----->>>"
pprint(globals())
print "-----tes001: locals(1)----->>>"
pprint(locals())
a = 345
print a
print "-----tes001: globals(2)----->>>"
pprint(globals())
print "-----tes001: locals(2)----->>>"
pprint(locals())
tes001()
print "-----top: globals(3)----->>>"
pprint(globals())
print "-----top: locals(3)----->>>"
pprint(locals())
Execution result
-----tes001: globals(1)----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes003.py',
'__name__': '__main__',
'__package__': None,
'a': 123,
'pprint': <function pprint at 0x02222770>,
'tes001': <function tes001 at 0x02222BB0>}
-----tes001: locals(1)----->>>
{}
345
-----tes001: globals(2)----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes003.py',
'__name__': '__main__',
'__package__': None,
'a': 123,
'pprint': <function pprint at 0x02222770>,
'tes001': <function tes001 at 0x02222BB0>}
-----tes001: locals(2)----->>>
{'a': 345}
-----top: globals(3)----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes003.py',
'__name__': '__main__',
'__package__': None,
'a': 123,
'pprint': <function pprint at 0x02222770>,
'tes001': <function tes001 at 0x02222BB0>}
-----top: locals(3)----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'tes003.py',
'__name__': '__main__',
'__package__': None,
'a': 123,
'pprint': <function pprint at 0x02222770>,
'tes001': <function tes001 at 0x02222BB0>}
This worked fine. In the output of tes001: globals (2), a is 123 and in the output of tes001: locals (2) 345. In tes001 (), the local variable a is rewritten, so the value of a when returning to the top level remains the value (123) before the function call. I understand the theory somehow, but it feels a little strange. Remove the print statement and try to arrange the code when it works and when it doesn't.
a = 123
def tes001():
print a
tes001()
a = 123
def tes001():
a = 345
print a
tes001()
a = 123
def tes001():
print a #UnboundLocalError
a = 345
tes001()
I've made various movements and gave reasons for the operation results, but looking at the above, it's still difficult to understand. I'd like to investigate a little more, but it's getting longer, so I'll stop here. I think I can explain the implementation of closures.
Recommended Posts