Closures (Livehacking Screenplay)¶
def
is a Statement¶
Demonstrate:
Functions are objects, just like integers are
def
used inside another function ⟶ local variablefunction as return value
# f() -> error
def f():
print('f called')
f()
g = f
g()
$ python code/05_functions_are_objects.py
f called
f called
|
|
def create_f():
def f():
print('inner f called')
return f
inner = create_f()
inner()
$ python code/10_create_function.py
inner f called
|
|
Global Scope¶
Variables in global scope can be accessed by “inner” functions (no surprise)
g = 1
def create_f():
def f():
print('inner f called, g =', g)
return f
inner = create_f()
inner()
$ python code/20_global_read.py
inner f called, g = 1
|
|
And Intermediate Scope?¶
Variables in the fnction containing the
def
?
def create_f():
intermediate = 1
def f():
print('inner f called, intermediate =', intermediate)
return f
inner = create_f()
inner()
$ python code/30_intermediate_closure.py
inner f called, intermediate = 1
|
|
A Less Theoretical “Use Case”¶
def create_f():
intermediate = 1
def f():
print('f called, intermediate =', intermediate)
return f
# inner = create_f()
# inner()
def print_it(msg):
def _p():
print(msg)
return _p
blah = print_it('blah')
something = print_it('something')
blah()
something()
$ python code/35_closure_use_case.py
blah
something
|
|
Assignment to Global Scope¶
Recap of
global
keyword… used inside inner function
g = 1
def create_f():
def f():
g = 2
print('inner f called, g =', g)
return f
inner = create_f()
inner()
print('global g =', g)
$ python code/40_global_assignment_wrong.py
inner f called, g = 2
global g = 1
|
|
g = 1
def create_f():
def f():
global g
g = 2
print('inner f called, g =', g)
return f
inner = create_f()
inner()
print('global g =', g)
$ python code/50_global_assignment_right.py
inner f called, g = 2
global g = 2
|
|
Assignment to Intermediate Scope¶
And now, what about assignment to intermediate scope? To a variable in the closure?
Who does this?
Many non-obvious use cases, used to improve job security
def create():
intermediate = 1
def assign():
intermediate = 2
print('assign: intermediate =', intermediate)
def check():
print('check: intermediate =', intermediate)
return assign, check
assign, check = create()
assign()
check()
$ python code/60_intermediate_assignment_wrong.py
assign: intermediate = 2
check: intermediate = 1
|
|
def create():
intermediate = 1
def assign():
nonlocal intermediate
intermediate = 2
print('assign: intermediate =', intermediate)
def check():
print('check: intermediate =', intermediate)
return assign, check
assign, check = create()
assign()
check()
$ python code/70_intermediate_assignment_right.py
assign: intermediate = 2
check: intermediate = 2
|
|