-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathunit6_lesson_01_understanding_nested_functions.py
More file actions
172 lines (137 loc) · 4.34 KB
/
Copy pathunit6_lesson_01_understanding_nested_functions.py
File metadata and controls
172 lines (137 loc) · 4.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
__author__ = 'Kalyan'
notes = '''
nested functions underlie many advanced features of python. So a basic understanding of this
feature is essential to mastering python.
nested functions are defined in the scope of a function, behave exactly the same except
that they have a read only access to variables in the outer function.
'''
from placeholders import *
def outer_func(outer_var):
def inner_func(inner_var):
return outer_var + inner_var
return inner_func
def test_inner_func_scope():
# inner_func not accessible by default
try:
inner_func()
except __: # fill up the exception
pass
# this syntax does not work either, it is not just static scoping.
try:
outer_func.inner_func()
except __ : # fillup the exception
pass
def test_inner_func_can_be_returned():
f1 = outer_func(10)
assert __ == type(f1).__name__
assert __ == f1(20)
def test_each_invocation_returns_a_new_func():
f1 = outer_func(10)
f2 = outer_func(10)
assert __ == (f1 is f2)
assert __ == (f1 == f2)
f3 = f2
assert __ == (f3 is f2)
assert __ == (f3 == f2)
def test_inner_func_has_access_to_outer_variables_after_return():
f1 = outer_func(20)
f2 = outer_func(50)
assert __ == f1(30)
assert __ == f1(40)
assert __ == f2(30)
assert __ == f2(40)
def print_attributes(obj):
for x in dir(obj):
print("attribute: " + x)
print(getattr(obj, x))
def test_inner_func_attributes():
f1 = outer_func(10)
assert __ == len(dir(f1)) #how many attributes does f1 have
# use the print_attributes function to explore the properties
# fill up the attribute name that you think holds a reference to the
# function scope variables
ref_to_outer_scope = __
# if you understand this, you have understood nested funcs :).
# Also a good idea to use the visualizer to understand this code...
def test_inner_func_late_binding():
def outer():
funcs = []
for x in range(5):
def inner():
return x
funcs.append(inner)
result = []
for func in funcs:
result.append(func())
return result
assert [__] == outer()
# just to re-iterate what you have learnt above. Search if this is not clear!
def test_inner_func_late_binding2():
def outer(nums):
def inner():
nums.append(10)
assert [__] == nums # see the function invocation below.
inner()
assert [__] == nums
# assign nums to another empty list
nums = []
inner()
assert [__] == nums
inner()
assert [__] == nums
return inner
# I have called all variables nums, so you can check if you understanding of names
# and scopes is right :-).
nums = [10, 20, 30]
f1 = outer(nums)
assert [__] == nums
f1()
assert [__] == nums
# generally you should not write code like this :), this is only to learn
def test_outer_scope_reads():
y = 30
def outer(x):
def inner1():
x = 30
return x
def inner2():
return x + y
def inner3():
# note what happens to outer y here
y = 10
return x + y
return [inner1(), inner2(), inner3(), x, y]
assert [__] == outer(20)
def test_outer_scope_write():
y = 10
def outer(x):
def inner1():
nonlocal y # this syntax allows you to bind to outer y
y = 40
return y
def inner2():
y = 30
return y
def inner3():
return y
return [x, y, inner1(), inner2(), inner3()]
assert [__] == outer(25)
# def is an executable statement. the function name is nothing more than a name
# binding to a code object! So same scope rules as variables apply to function names.
# read up more at http://effbot.org/zone/default-values.htm
def test_def_is_a_statement():
def outer(x):
if x > 10:
def f():
return x * 2
else:
def f():
return x * 3
return f
assert __ == outer(20)()
assert __ == outer(5)()
three_things_i_learnt = """
-
-
-
"""