functions that take input
To review, a function_ is code that is callable, which means I can write code to do something one time, and call the name for it to do that thing at a different time from when I write it.
functions_ can make code simpler, easier to read, test, reuse, maintain and improve - all the good things.
Part of Computer Programming is sending input data to a process and getting output data back
input_data -> process -> output_data
where process is the function_. I think of it like mapping a function f in Mathematics with inputs x and output y
in other words
f(x) -> y
function(input_data) -> output_data
the function does something (the process) with input_data and returns output_data as the result.
how to make a function that takes input
functions_ are made with
the def keyword
a name
parentheses and a colon at the end
the code that makes up the function (its body) comes after the colon
def name_of_function(input_data):
the body of the function
return output_data
preview
I have these tests by the end of the chapter
1import src.functions
2import unittest
3
4
5def add_x(number):
6 # return 2 + number
7 return 3 + number
8
9
10class TestFunctions(unittest.TestCase):
11
12 first = 'first'
13 last = 'last'
14 a_tuple = (1, 2, 3, 'n')
15 a_list = [1, 2, 3, 'n']
16 first_number = 0
17 second_number = 1
18
19 def test_why_use_a_function(self):
20 # reality = 1 + 0
21 # reality = 2 + 0
22 reality = add_x(0)
23 # my_expectation = 0
24 # my_expectation = 1
25 # my_expectation = 2
26 my_expectation = 3
27 self.assertEqual(reality, my_expectation)
28
29 # reality = 1 + 1
30 # reality = 2 + 1
31 reality = add_x(1)
32 # my_expectation = 1
33 # my_expectation = 2
34 # my_expectation = 3
35 my_expectation = 4
36 self.assertEqual(reality, my_expectation)
37
38 # reality = 1 + 2
39 # reality = 2 + 2
40 reality = add_x(2)
41 # my_expectation = 2
42 # my_expectation = 3
43 # my_expectation = 4
44 my_expectation = 5
45 self.assertEqual(reality, my_expectation)
46
47 # reality = 1 + 3
48 # reality = 2 + 3
49 reality = add_x(3)
50 # my_expectation = 3
51 # my_expectation = 4
52 # my_expectation = 5
53 my_expectation = 6
54 self.assertEqual(reality, my_expectation)
55
56 # reality = 1 + 4
57 # reality = 2 + 4
58 reality = add_x(4)
59 # my_expectation = 4
60 # my_expectation = 5
61 # my_expectation = 6
62 my_expectation = 7
63 self.assertEqual(reality, my_expectation)
64
65 # reality = 1 + 5
66 # reality = 2 + 5
67 reality = add_x(5)
68 # my_expectation = 5
69 # my_expectation = 6
70 # my_expectation = 7
71 my_expectation = 8
72 self.assertEqual(reality, my_expectation)
73
74 # reality = 1 + 6
75 # reality = 2 + 6
76 reality = add_x(6)
77 # my_expectation = 6
78 # my_expectation = 7
79 # my_expectation = 8
80 my_expectation = 9
81 self.assertEqual(reality, my_expectation)
82
83 # reality = 1 + 7
84 # reality = 2 + 7
85 reality = add_x(7)
86 # my_expectation = 7
87 # my_expectation = 8
88 # my_expectation = 9
89 my_expectation = 10
90 self.assertEqual(reality, my_expectation)
91
92 # reality = 1 + 8
93 # reality = 2 + 8
94 reality = add_x(8)
95 # my_expectation = 8
96 # my_expectation = 9
97 # my_expectation = 10
98 my_expectation = 11
99 self.assertEqual(reality, my_expectation)
100
101 # reality = 1 + 9
102 # reality = 2 + 9
103 reality = add_x(9)
104 # my_expectation = 9
105 # my_expectation = 10
106 # my_expectation = 11
107 my_expectation = 12
108 self.assertEqual(reality, my_expectation)
109
110 def test_making_a_function_w_pass(self):
111 self.assertIs(src.functions.w_pass(), None)
112
113 def test_making_a_function_w_return(self):
114 self.assertIs(src.functions.w_return(), None)
115
116 def test_making_a_function_w_return_none(self):
117 self.assertIs(
118 src.functions.w_return_none(), None
119 )
120
121 def test_what_happens_after_a_function_returns(self):
122 self.assertIs(
123 src.functions.return_is_last(), None
124 )
125
126 def test_constant_function(self):
127 reality = src.functions.constant()
128 my_expectation = 'the same thing'
129 self.assertEqual(reality, my_expectation)
130
131 def test_identity_function(self):
132 reality = src.functions.identity(None)
133 my_expectation = None
134 self.assertEqual(reality, my_expectation)
135
136 reality = src.functions.identity(object)
137 my_expectation = object
138 self.assertEqual(reality, my_expectation)
139
140 def test_w_positional_arguments(self):
141 reality = src.functions.w_positional_arguments(
142 self.first, self.last,
143 )
144 my_expectation = (self.first, self.last)
145 self.assertEqual(reality, my_expectation)
146
147 reality = src.functions.w_positional_arguments(
148 self.last, self.first,
149 )
150 my_expectation = (self.last, self.first)
151 self.assertEqual(reality, my_expectation)
152
153 reality = src.functions.w_positional_arguments(
154 self.first_number, self.second_number,
155 )
156 my_expectation = (
157 self.first_number, self.second_number
158 )
159 self.assertEqual(reality, my_expectation)
160
161 reality = src.functions.w_positional_arguments(
162 self.a_tuple, self.a_list,
163 )
164 my_expectation = (self.a_tuple, self.a_list)
165 self.assertEqual(reality, my_expectation)
166
167 def test_w_keyword_arguments(self):
168 reality = src.functions.w_keyword_arguments(
169 first_input=self.first,
170 last_input=self.last,
171 )
172 my_expectation = (self.first, self.last)
173 self.assertEqual(reality, my_expectation)
174
175 reality = src.functions.w_keyword_arguments(
176 last_input=self.last,
177 first_input=self.first,
178 )
179 my_expectation = (self.first, self.last)
180 self.assertEqual(reality, my_expectation)
181
182 reality = src.functions.w_keyword_arguments(
183 self.last, self.first,
184 )
185 my_expectation = (self.last, self.first)
186 self.assertEqual(reality, my_expectation)
187
188 reality = src.functions.w_keyword_arguments(
189 last_input=self.first_number,
190 first_input=self.second_number,
191 )
192 my_expectation = (
193 self.second_number, self.first_number
194 )
195 self.assertEqual(reality, my_expectation)
196
197 a_set = {1, 2, 3, 'n'}
198 a_dictionary = {'key': 'value'}
199 reality = src.functions.w_keyword_arguments(
200 first_input=a_set,
201 last_input=a_dictionary,
202 )
203 my_expectation = (a_set, a_dictionary)
204 self.assertEqual(reality, my_expectation)
205
206 reality = src.functions.w_positional_arguments(
207 first_input=self.a_list,
208 last_input=self.a_tuple,
209 )
210 my_expectation = (self.a_list, self.a_tuple)
211 self.assertEqual(reality, my_expectation)
212
213 def test_w_args_and_kwargs(self):
214 reality = (
215 src.functions.w_args_and_kwargs(
216 self.first, last_input=self.last,
217 )
218 )
219 my_expectation = (self.first, self.last)
220 self.assertEqual(reality, my_expectation)
221
222 def test_w_optional_arguments(self):
223 first_name, last_name = 'jane', 'doe'
224 reality = src.functions.w_optional_arguments(
225 first_name,
226 )
227 my_expectation = (first_name, last_name)
228 self.assertEqual(reality, my_expectation)
229
230 first_name, blow = 'joe', 'blow'
231 reality = src.functions.w_optional_arguments(
232 first_name, blow,
233 )
234 my_expectation = (first_name, blow)
235 self.assertEqual(reality, my_expectation)
236
237 first_name = 'john'
238 reality = src.functions.w_optional_arguments(
239 first_input=first_name,
240 )
241 my_expectation = (first_name, last_name)
242 self.assertEqual(reality, my_expectation)
243
244 last_name = 'smith'
245 reality = src.functions.w_optional_arguments(
246 last_input=last_name,
247 first_input=first_name,
248 )
249 my_expectation = (first_name, last_name)
250 self.assertEqual(reality, my_expectation)
251
252 def test_w_unknown_arguments(self):
253 a_tuple = (0, 1)
254 a_dictionary = {'a': 2, 'b': 3}
255 reality = src.functions.w_unknown_arguments(
256 *a_tuple, **a_dictionary
257 )
258 my_expectation = (a_tuple, a_dictionary)
259 self.assertEqual(reality, my_expectation)
260
261 a_tuple = (0, 1)
262 a_dictionary = {'a': 2, 'b': 3, 'c': 4}
263 reality = src.functions.w_unknown_arguments(
264 *a_tuple, **a_dictionary
265 )
266 my_expectation = (
267 a_tuple, a_dictionary
268 )
269 self.assertEqual(reality, my_expectation)
270
271 a_tuple = (0, 1, 2)
272 a_dictionary = {'a': 3, 'b': 4, 'c': 5}
273 reality = src.functions.w_unknown_arguments(
274 *a_tuple, **a_dictionary,
275 )
276 my_expectation = (
277 a_tuple, a_dictionary
278 )
279 self.assertEqual(reality, my_expectation)
280
281 a_tuple = (0, 1, 2, 3)
282 reality = src.functions.w_unknown_arguments(
283 *a_tuple
284 )
285 my_expectation = (a_tuple, {})
286 self.assertEqual(reality, my_expectation)
287
288 a_dictionary = {'a': 4, 'b': 5, 'c': 6, 'd': 7}
289 reality = src.functions.w_unknown_arguments(
290 **a_dictionary
291 )
292 my_expectation = ((), a_dictionary)
293 self.assertEqual(reality, my_expectation)
294
295 reality = src.functions.w_unknown_arguments()
296 my_expectation = ((), {})
297 self.assertEqual(reality, my_expectation)
298
299
300# Exceptions seen
301# AssertionError
302# NameError
303# AttributeError
304# TypeError
305# SyntaxError
questions about functions that take input
Questions to think about as I go through the chapter
open the project
I open a terminal
I change directory to the project
cd functionsthe terminal shows I am in the
functionsfolder.../pumping_python/functionsI open
test_functions.pyI use pytest-watcher to run the tests automatically
uv run pytest-watcher . --nowthe terminal shows
test_functions.py ..... [100%] =================== 5 passed in X.YZs ====================
test_identity_function
A function can take input, and the simplest thing it can do is return the input as output, it is called the Identity or Passthrough function and is also in the Truth Table chapter in test_logical_identity.
RED: make it fail
I add a test to test_functions.py
30def test_constant_function():
31 def constant():
32 return 'the same thing'
33
34 assert constant() is 'the same thing'
35
36
37def test_identity_function():
38 assert identity() == None
39
40
41# Exceptions seen
the terminal is my friend, and shows NameError
NameError: name 'identity' is not defined
is it because test_functions.py has no identity?
GREEN: make it pass
I add a function for identity
37def test_identity_function():
38 def identity():
39 return None
40
41 assert identity() == None
42
43
44# Exceptions seen
the test passes.
how to call a function with input
I can call a function with input by placing an object in parentheses when I call it.
RED: make it fail
I add input to the function call
37def test_identity_function():
38 def identity():
39 return None
40
41 # assert identity() == None
42 assert identity(None) == None
43
44
45# Exceptions seen
the terminal is my friend, and shows TypeError
TypeError:
test_identity_function.<locals>.identity()
takes 0 positional arguments but 1 was given
because
I called
identitywhich belongs totest_identity_functionwith one input (None).The function definition (signature) of
identitydoes not allow any inputs when it is called, since the parentheses are empty.I am violating the function signature when I call it in a way that it was not designed to be called which raises TypeError.
GREEN: make it pass
I add a name in parentheses for the identity function to take input
37def test_identity_function():
38 # def identity():
39 def identity(the_input):
40 return None
41
42 # assert identity() == None
43 assert identity(None) == None
44
45
46# Exceptions seen
the test passes. I am genius.
REFACTOR: make it better
The description for the identity function is that it returns the same thing it is given, this test passes when None is given as input.
Does it pass when another value is given or does it always return None? There is one way to find out
I add an assertion to test_identity_function in
37def test_identity_function(): 38 # def identity(): 39 def identity(the_input): 40 return None 41 42 # assert identity() == None 43 assert identity(None) == None 44 assert identity(object) == object 45 46 47# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert None == objectbecause when I call
identityit returns None. Using substitution since I can treat a call to a function as the object it returnsassert identity(object) == object assert None == objectwhich raises AssertionError since None is only equal to None
object is the mother of everything in Python. everything in Python is an object (they inherit from it). I am not all the way genius, yet.
I make the
identityfunction return what it gets37def test_identity_function(): 38 # def identity(): 39 def identity(the_input): 40 # return None 41 return the_input 42 43 # assert identity() == None 44 assert identity(None) == None 45 assert identity(object) == object 46 47 48# Exceptions seenthe test passes.
I remove the commented lines
37def test_identity_function(): 38 def identity(the_input): 39 return the_input 40 41 assert identity(None) == None 42 assert identity(object) == object 43 44 45# Exceptions seenI add a git commit message in the other terminal
git commit --all --message \ 'add test_identity_function'the terminal shows a summary of the changes then goes back to the command line.
The Identity Function returns its input as output.
I sometimes use the Identity Function when I am testing, to check connections. If I can send something (input) and get it back, I can start making changes to see how it affects the output.
test_why_use_a_function
Why would I use a function when I can just write code to do the thing I want? Let us assume I am writing a program to add up numbers.
RED: make it fail
I add a test
37def test_identity_function(): 38 def identity(the_input): 39 return the_input 40 41 assert identity(None) == None 42 assert identity(object) == object 43 44 45def test_why_use_a_function(): 46 assert 1 + 0 == 0 47 48 49# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert (1 + 0) == 0because
1 + 0is NOT equal to0.
GREEN: make it pass
I change the assertion to make it True
45def test_why_use_a_function():
46 # assert 1 + 0 == 0
47 assert 1 + 0 == 1
48
49
50# Exceptions seen
the test passes.
REFACTOR: make it better
I add an assertion for
1 + 145def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 assert 1 + 1 == 1 49 50 51# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert (1 + 1) == 1because
1 + 1is NOT equal to1.I change the assertion to make it True
45def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 51 52# Exceptions seenthe test passes.
I add an assertion for
1 + 245def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 assert 1 + 2 == 2 51 52 53# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert (1 + 2) == 2because
1 + 2is NOT equal to2.I change the assertion to make it True
45def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 53 54# Exceptions seenthe test passes.
I add an assertion for
1 + 345def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 assert 1 + 3 == 3 53 54 55# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert (1 + 3) == 3because
1 + 3is NOT equal to3.I change the assertion to make it True
45def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 55 56# Exceptions seenthe test passes.
I add an assertion for
1 + 345def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 assert 1 + 3 == 3 53 54 55# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert (1 + 3) == 3because
1 + 3is NOT equal to3.I change the assertion to make it True
45def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 4 == 2 51 assert 1 + 4 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 55 56# Exceptions seenthe test passes.
I add an assertion for
1 + 445def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 assert 1 + 4 == 4 55 56 57# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert (1 + 4) == 4because
1 + 4is NOT equal to4.I change the assertion to make it True
45def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 # assert 1 + 4 == 4 55 assert 1 + 4 == 5 56 57 58# Exceptions seenthe test passes.
I add an assertion for
1 + 545def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 # assert 1 + 4 == 4 55 assert 1 + 4 == 5 56 assert 1 + 5 == 5 57 58 59# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert (1 + 5) == 5because
1 + 5is NOT equal to5.I change the assertion to make it True
45def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 # assert 1 + 4 == 4 55 assert 1 + 4 == 5 56 # assert 1 + 5 == 5 57 assert 1 + 5 == 6 58 59 60# Exceptions seenthe test passes.
I add an assertion for
1 + 645def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 # assert 1 + 4 == 4 55 assert 1 + 4 == 5 56 # assert 1 + 5 == 5 57 assert 1 + 5 == 6 58 assert 1 + 6 == 6 59 60 61# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert (1 + 6) == 6because
1 + 6is NOT equal to6.I change the assertion to make it True
45def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 # assert 1 + 4 == 4 55 assert 1 + 4 == 5 56 # assert 1 + 5 == 5 57 assert 1 + 5 == 6 58 # assert 1 + 6 == 6 59 assert 1 + 6 == 7 60 61 62# Exceptions seenthe test passes.
I add an assertion for
1 + 745def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 # assert 1 + 4 == 4 55 assert 1 + 4 == 5 56 # assert 1 + 5 == 5 57 assert 1 + 5 == 6 58 # assert 1 + 6 == 6 59 assert 1 + 6 == 7 60 assert 1 + 7 == 7 61 62 63# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert (1 + 7) == 7because
1 + 7is NOT equal to7.I change the assertion to make it True
45def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 # assert 1 + 4 == 4 55 assert 1 + 4 == 5 56 # assert 1 + 5 == 5 57 assert 1 + 5 == 6 58 # assert 1 + 6 == 6 59 assert 1 + 6 == 7 60 # assert 1 + 7 == 7 61 assert 1 + 7 == 8 62 63 64# Exceptions seenthe test passes.
I add an assertion for
1 + 845def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 # assert 1 + 4 == 4 55 assert 1 + 4 == 5 56 # assert 1 + 5 == 5 57 assert 1 + 5 == 6 58 # assert 1 + 6 == 6 59 assert 1 + 6 == 7 60 # assert 1 + 7 == 7 61 assert 1 + 7 == 8 62 assert 1 + 8 == 8 63 64 65# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert (1 + 8) == 8because
1 + 8is NOT equal to8.I change the assertion to make it True
45def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 # assert 1 + 4 == 4 55 assert 1 + 4 == 5 56 # assert 1 + 5 == 5 57 assert 1 + 5 == 6 58 # assert 1 + 6 == 6 59 assert 1 + 6 == 7 60 # assert 1 + 7 == 7 61 assert 1 + 7 == 8 62 # assert 1 + 8 == 8 63 assert 1 + 8 == 9 64 65 66# Exceptions seenthe test passes.
I add an assertion for
1 + 945def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 # assert 1 + 4 == 4 55 assert 1 + 4 == 5 56 # assert 1 + 5 == 5 57 assert 1 + 5 == 6 58 # assert 1 + 6 == 6 59 assert 1 + 6 == 7 60 # assert 1 + 7 == 7 61 assert 1 + 7 == 8 62 # assert 1 + 8 == 8 63 assert 1 + 8 == 9 64 assert 1 + 9 == 9 65 66 67# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert (1 + 9) == 9because
1 + 9is NOT equal to9.I change the assertion to make it True
45def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 assert 1 + 0 == 1 48 # assert 1 + 1 == 1 49 assert 1 + 1 == 2 50 # assert 1 + 2 == 2 51 assert 1 + 2 == 3 52 # assert 1 + 3 == 3 53 assert 1 + 3 == 4 54 # assert 1 + 4 == 4 55 assert 1 + 4 == 5 56 # assert 1 + 5 == 5 57 assert 1 + 5 == 6 58 # assert 1 + 6 == 6 59 assert 1 + 6 == 7 60 # assert 1 + 7 == 7 61 assert 1 + 7 == 8 62 # assert 1 + 8 == 8 63 assert 1 + 8 == 9 64 # assert 1 + 9 == 9 65 assert 1 + 9 == 10 66 67 68# Exceptions seenthe test passes.
all those assertions test what happens when I add a number to
1. If I want to test what happens when I add a number to2, I would have to change1in 10 places. I change1to2for the calculation part of the assertions45def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 # assert 1 + 0 == 1 48 assert 2 + 0 == 1 49 # assert 1 + 1 == 1 50 # assert 1 + 1 == 2 51 assert 2 + 1 == 2 52 # assert 1 + 2 == 2 53 # assert 1 + 2 == 3 54 assert 2 + 2 == 3 55 # assert 1 + 3 == 3 56 # assert 1 + 3 == 4 57 assert 2 + 3 == 4 58 # assert 1 + 4 == 4 59 # assert 1 + 4 == 5 60 assert 2 + 4 == 5 61 # assert 1 + 5 == 5 62 # assert 1 + 5 == 6 63 assert 2 + 5 == 6 64 # assert 1 + 6 == 6 65 # assert 1 + 6 == 7 66 assert 2 + 6 == 7 67 # assert 1 + 7 == 7 68 # assert 1 + 7 == 8 69 assert 2 + 7 == 8 70 # assert 1 + 8 == 8 71 # assert 1 + 8 == 9 72 assert 2 + 8 == 9 73 # assert 1 + 9 == 9 74 # assert 1 + 9 == 10 75 assert 2 + 9 == 10 76 77 78# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert (2 + 0) == 1I change the result side of each assertion to make them True
45def test_why_use_a_function(): 46 # assert 1 + 0 == 0 47 # assert 1 + 0 == 1 48 # assert 2 + 0 == 1 49 assert 2 + 0 == 2 50 # assert 1 + 1 == 1 51 # assert 1 + 1 == 2 52 # assert 2 + 1 == 2 53 assert 2 + 1 == 3 54 # assert 1 + 2 == 2 55 # assert 1 + 2 == 3 56 # assert 2 + 2 == 3 57 assert 2 + 2 == 4 58 # assert 1 + 3 == 3 59 # assert 1 + 3 == 4 60 # assert 2 + 3 == 4 61 assert 2 + 3 == 5 62 # assert 1 + 4 == 4 63 # assert 1 + 4 == 5 64 # assert 2 + 4 == 5 65 assert 2 + 4 == 6 66 # assert 1 + 5 == 5 67 # assert 1 + 5 == 6 68 # assert 2 + 5 == 6 69 assert 2 + 5 == 7 70 # assert 1 + 6 == 6 71 # assert 1 + 6 == 7 72 # assert 2 + 6 == 7 73 assert 2 + 6 == 8 74 # assert 1 + 7 == 7 75 # assert 1 + 7 == 8 76 # assert 2 + 7 == 8 77 assert 2 + 7 == 9 78 # assert 1 + 8 == 8 79 # assert 1 + 8 == 9 80 # assert 2 + 8 == 9 81 assert 2 + 8 == 10 82 # assert 1 + 9 == 9 83 # assert 1 + 9 == 10 84 # assert 2 + 9 == 10 85 assert 2 + 9 == 11 86 87 88# Exceptions seenthe test passes.
I add a git commit message
git commit --all --message \ 'add test_why_use_a_function'the terminal shows a summary of the changes then goes back to the command line.
I go back to the terminal where the tests are running
What if I want to test what happens when I add
3to a number? Wait! No more, please! I do not want to have to make a change for each new number, there has to be a better way. I can use a function for the parts that repeat. I add one45def test_why_use_a_function(): 46 def add_x(number): 47 return 2 + number 48 49 # assert 1 + 0 == 0 50 # assert 1 + 0 == 1 51 # assert 2 + 0 == 1 52 assert 2 + 0 == 2I use the new function for the calculation in the first assertion
45def test_why_use_a_function(): 46 def add_x(number): 47 return 2 + number 48 49 # assert 1 + 0 == 0 50 # assert 1 + 0 == 1 51 # assert 2 + 0 == 1 52 # assert 2 + 0 == 2 53 assert add_x(0) == 2 54 # assert 1 + 1 == 1 55 # assert 1 + 1 == 2 56 # assert 2 + 1 == 2 57 assert 2 + 1 == 3the test is still green because when I call
add_xwith a number as input, it returns2plus the number as output. Using substitution since I can treat a call to a function as the object it returnsassert add_x(0) == 2 # inside add_x add_x(number) add_x(0) # add_x returns 2 + number 2 + 0 == 22 + 0is equal to2.I use the
add_xfunction for the other assertions45def test_why_use_a_function(): 46 def add_x(number): 47 return 2 + number 48 49 # assert 1 + 0 == 0 50 # assert 1 + 0 == 1 51 # assert 2 + 0 == 1 52 # assert 2 + 0 == 2 53 assert add_x(0) == 2 54 # assert 1 + 1 == 1 55 # assert 1 + 1 == 2 56 # assert 2 + 1 == 2 57 # assert 2 + 1 == 3 58 assert add_x(1) == 3 59 # assert 1 + 2 == 2 60 # assert 1 + 2 == 3 61 # assert 2 + 2 == 3 62 # assert 2 + 2 == 4 63 assert add_x(2) == 4 64 # assert 1 + 3 == 3 65 # assert 1 + 3 == 4 66 # assert 2 + 3 == 4 67 # assert 2 + 3 == 5 68 assert add_x(3) == 5 69 # assert 1 + 4 == 4 70 # assert 1 + 4 == 5 71 # assert 2 + 4 == 5 72 # assert 2 + 4 == 6 73 assert add_x(4) == 6 74 # assert 1 + 5 == 5 75 # assert 1 + 5 == 6 76 # assert 2 + 5 == 6 77 # assert 2 + 5 == 7 78 assert add_x(5) == 7 79 # assert 1 + 6 == 6 80 # assert 1 + 6 == 7 81 # assert 2 + 6 == 7 82 # assert 2 + 6 == 8 83 assert add_x(6) == 8 84 # assert 1 + 7 == 7 85 # assert 1 + 7 == 8 86 # assert 2 + 7 == 8 87 # assert 2 + 7 == 9 88 assert add_x(7) == 9 89 # assert 1 + 8 == 8 90 # assert 1 + 8 == 9 91 # assert 2 + 8 == 9 92 # assert 2 + 8 == 10 93 assert add_x(8) == 10 94 # assert 1 + 9 == 9 95 # assert 1 + 9 == 10 96 # assert 2 + 9 == 10 97 # assert 2 + 9 == 11 98 assert add_x(9) == 11 99 100 101# Exceptions seenstill green.
Now I only have to make a change in one place if I want to test what happens if I add
3to a number45def test_why_use_a_function(): 46 def add_x(number): 47 # return 2 + number 48 return 3 + number 49 50 # assert 1 + 0 == 0 51 # assert 1 + 0 == 1 52 # assert 2 + 0 == 1 53 # assert 2 + 0 == 2 54 assert add_x(0) == 2the terminal is my friend, and shows AssertionError
E assert 3 == 2I change the results part of the assertions one at a time
45def test_why_use_a_function(): 46 def add_x(number): 47 # return 2 + number 48 return 3 + number 49 50 # assert 1 + 0 == 0 51 # assert 1 + 0 == 1 52 # assert 2 + 0 == 1 53 # assert 2 + 0 == 2 54 # assert add_x(0) == 2 55 assert add_x(0) == 3 56 # assert 1 + 1 == 1 57 # assert 1 + 1 == 2 58 # assert 2 + 1 == 2 59 # assert 2 + 1 == 3 60 # assert add_x(1) == 3 61 assert add_x(1) == 4 62 # assert 1 + 2 == 2 63 # assert 1 + 2 == 3 64 # assert 2 + 2 == 3 65 # assert 2 + 2 == 4 66 # assert add_x(2) == 4 67 assert add_x(2) == 5 68 # assert 1 + 3 == 3 69 # assert 1 + 3 == 4 70 # assert 2 + 3 == 4 71 # assert 2 + 3 == 5 72 # assert add_x(3) == 5 73 assert add_x(3) == 6 74 # assert 1 + 4 == 4 75 # assert 1 + 4 == 5 76 # assert 2 + 4 == 5 77 # assert 2 + 4 == 6 78 # assert add_x(4) == 6 79 assert add_x(4) == 7 80 # assert 1 + 5 == 5 81 # assert 1 + 5 == 6 82 # assert 2 + 5 == 6 83 # assert 2 + 5 == 7 84 # assert add_x(5) == 7 85 assert add_x(5) == 8 86 # assert 1 + 6 == 6 87 # assert 1 + 6 == 7 88 # assert 2 + 6 == 7 89 # assert 2 + 6 == 8 90 # assert add_x(6) == 8 91 assert add_x(6) == 9 92 # assert 1 + 7 == 7 93 # assert 1 + 7 == 8 94 # assert 2 + 7 == 8 95 # assert 2 + 7 == 9 96 # assert add_x(7) == 9 97 assert add_x(7) == 10 98 # assert 1 + 8 == 8 99 # assert 1 + 8 == 9 100 # assert 2 + 8 == 9 101 # assert 2 + 8 == 10 102 # assert add_x(8) == 10 103 assert add_x(8) == 11 104 # assert 1 + 9 == 9 105 # assert 1 + 9 == 10 106 # assert 2 + 9 == 10 107 # assert 2 + 9 == 11 108 # assert add_x(9) == 11 109 assert add_x(9) == 12 110 111 112# Exceptions seenthe test passes.
I remove the commented lines
45def test_why_use_a_function(): 46 def add_x(number): 47 return 3 + number 48 49 assert add_x(0) == 3 50 assert add_x(1) == 4 51 assert add_x(2) == 5 52 assert add_x(3) == 6 53 assert add_x(4) == 7 54 assert add_x(5) == 8 55 assert add_x(6) == 9 56 assert add_x(7) == 10 57 assert add_x(8) == 11 58 assert add_x(9) == 12 59 60 61# Exceptions seenI add a git commit message in the other terminal
git commit --all --message \ 'extract add_x function'the terminal shows a summary of the changes then goes back to the command line.
I can use a function to remove repetition. Is there a better way to handle the changing results?
test_w_positional_arguments
test_identity_function used one input, these next tests use functions that take more than one input.
RED: make it fail
I go back to the terminal where the tests are running
I add a test
58 assert add_x(9) == 12 59 60 61def test_w_positional_arguments(): 62 assert w_positional_arguments() == None 63 64 65# Exceptions seenthe terminal is my friend, and shows NameError
NameError: name 'w_positional_arguments' is not definedbecause …
GREEN: make it pass
I add the function
61def test_w_positional_arguments():
62 def w_positional_arguments():
63 return None
64
65 assert w_positional_arguments() == None
66
67
68# Exceptions seen
the test passes.
REFACTOR: make it better
I add input to the function call
61def test_w_positional_arguments(): 62 def w_positional_arguments(): 63 return None 64 65 # assert w_positional_arguments() == None 66 assert w_positional_arguments('first') == None 67 68 69# Exceptions seenthe terminal is my friend, and shows TypeError
TypeError: test_w_positional_arguments.<locals>.w_positional_arguments() takes 0 positional arguments but 1 was givenbecause
I called
w_positional_argumentswhich belongs totest_w_positional_argumentswith one input ('first').The function definition (signature) of
w_positional_argumentsdoes not allow any inputs when it is called, since the parentheses are empty.I am violating the function signature when I call it in a way that it was not designed to be called which raises TypeError.
I make the function take input by adding a name in parentheses
61def test_w_positional_arguments(): 62 # def w_positional_arguments(): 63 def w_positional_arguments(first_input): 64 return None 65 66 # assert w_positional_arguments() == None 67 assert w_positional_arguments('first') == None 68 69 70# Exceptions seenthe test passes.
I add another input to the function call
61def test_w_positional_arguments(): 62 # def w_positional_arguments(): 63 def w_positional_arguments(first_input): 64 return None 65 66 # assert w_positional_arguments() == None 67 # assert w_positional_arguments('first') == None 68 assert w_positional_arguments('first', 'last') == None 69 70 71# Exceptions seenthe terminal is my friend, and shows TypeError
TypeError: test_w_positional_arguments.<locals>.w_positional_arguments() takes 1 positional arguments but 2 was givenbecause
I called
w_positional_argumentswhich belongs totest_w_positional_argumentswith two inputs('first'and'last').The function definition (signature) of
w_positional_argumentsonly allows one input.I am violating the function signature when I call it in a way that it was not designed to be called which raises TypeError.
I make the function take another input by adding a name in parentheses
61def test_w_positional_arguments(): 62 # def w_positional_arguments(): 63 # def w_positional_arguments(first_input): 64 def w_positional_arguments(first_input, last_input): 65 return None 66 67 # assert w_positional_arguments() == None 68 # assert w_positional_arguments('first') == None 69 assert w_positional_arguments('first', 'last') == None 70 71 72# Exceptions seenthe test passes.
I change the expectation of the assertion
65def test_w_positional_arguments(): 66 # def w_positional_arguments(): 67 # def w_positional_arguments(first_input): 68 def w_positional_arguments(first_input, last_input): 69 return None 70 71 # assert w_positional_arguments() == None 72 # assert w_positional_arguments('first') == None 73 # assert w_positional_arguments('first', 'last') == None 74 assert ( 75 w_positional_arguments('first', 'last') 76 == ('first', 'last') 77 ) 78 79 80# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: assert None == ('first', 'last')because when I call
w_positional_argumentswith'first'and'last'as inputs, it returnsNone. Using substitution since I can treat a call to a function as the object it returnsw_positional_arguments('first' , 'last' ) == ('first', 'last') w_positional_arguments(first_input, last_input) return Noneassert w_positional_arguments('first', 'last') == ('first', 'last') assert None == ('first', 'last')which raises AssertionError since None is not a tuple.
I change the return statement to make the function return its inputs as output
61def test_w_positional_arguments(): 62 # def w_positional_arguments(): 63 # def w_positional_arguments(first_input): 64 def w_positional_arguments(first_input, last_input): 65 # return None 66 return first_input, last_input 67 68 # assert w_positional_arguments() == None 69 # assert w_positional_arguments('first') == None 70 # assert w_positional_arguments('first', 'last') == None 71 assert ( 72 w_positional_arguments('first', 'last') 73 == ('first', 'last') 74 ) 75 76 77# Exceptions seenthe test passes, because the function always returns
first_input, last_inputand the call in the test sends'first'asfirst_inputand'last'aslast_input.The problem with giving arguments this way is that they always have to be in the order the function expects or I get something different. I add an assertion to show this
61def test_w_positional_arguments(): 62 # def w_positional_arguments(): 63 # def w_positional_arguments(first_input): 64 def w_positional_arguments(first_input, last_input): 65 # return None 66 return first_input, last_input 67 68 # assert w_positional_arguments() == None 69 # assert w_positional_arguments('first') == None 70 # assert w_positional_arguments('first', 'last') == None 71 assert ( 72 w_positional_arguments('first', 'last') 73 == ('first', 'last') 74 ) 75 assert ( 76 w_positional_arguments('last', 'first') 77 == ('first', 'last') 78 ) 79 80 81# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: assert ('last', 'first') == ('first', 'last')because the function always returns
first_input, last_inputand the call in this test sends'last'asfirst_inputand'first'aslast_input. Using substitution since I can treat a call to a function as the object it returnsw_positional_arguments('last' , 'first' ) w_positional_arguments(first_input, last_input) return first_input, last_input return 'last' , 'first'assert w_positional_arguments('last', 'first') == ('first', 'last') assert ('last', 'first') == ('first', 'last')I change my expectation to match reality
61def test_w_positional_arguments(): 62 # def w_positional_arguments(): 63 # def w_positional_arguments(first_input): 64 def w_positional_arguments(first_input, last_input): 65 # return None 66 return first_input, last_input 67 68 # assert w_positional_arguments() == None 69 # assert w_positional_arguments('first') == None 70 # assert w_positional_arguments('first', 'last') == None 71 assert ( 72 w_positional_arguments('first', 'last') 73 == ('first', 'last') 74 ) 75 assert ( 76 w_positional_arguments('last', 'first') 77 # == ('first', 'last') 78 == ('last', 'first') 79 ) 80 81 82# Exceptions seenthe test passes.
I add variables for
'first'and'last'61def test_w_positional_arguments(): 62 # def w_positional_arguments(): 63 # def w_positional_arguments(first_input): 64 def w_positional_arguments(first_input, last_input): 65 # return None 66 return first_input, last_input 67 68 # assert w_positional_arguments() == None 69 # assert w_positional_arguments('first') == None 70 # assert w_positional_arguments('first', 'last') == None 71 72 first, last = 'first', 'last' 73 74 assert ( 75 w_positional_arguments('first', 'last') 76 == ('first', 'last') 77 ) 78 assert ( 79 w_positional_arguments('last', 'first') 80 # == ('first', 'last') 81 == ('last', 'first') 82 ) 83 84 85# Exceptions seenI use the variables to remove repetition of
'first'and'last'61def test_w_positional_arguments(): 62 # def w_positional_arguments(): 63 # def w_positional_arguments(first_input): 64 def w_positional_arguments(first_input, last_input): 65 # return None 66 return first_input, last_input 67 68 # assert w_positional_arguments() == None 69 # assert w_positional_arguments('first') == None 70 # assert w_positional_arguments('first', 'last') == None 71 72 first, last = 'first', 'last' 73 74 assert ( 75 # w_positional_arguments('first', 'last') 76 # == ('first', 'last') 77 w_positional_arguments(first, last) 78 == (first, last) 79 ) 80 assert ( 81 # w_positional_arguments('last', 'first') 82 # == ('first', 'last') 83 # == ('last', 'first') 84 w_positional_arguments(last, first) 85 == (last, first) 86 ) 87 88 89# Exceptions seenthe test is still green.
I add another assertion
61def test_w_positional_arguments(): 62 # def w_positional_arguments(): 63 # def w_positional_arguments(first_input): 64 def w_positional_arguments(first_input, last_input): 65 # return None 66 return first_input, last_input 67 68 # assert w_positional_arguments() == None 69 # assert w_positional_arguments('first') == None 70 # assert w_positional_arguments('first', 'last') == None 71 72 first, last = 'first', 'last' 73 74 assert ( 75 # w_positional_arguments('first', 'last') 76 # == ('first', 'last') 77 w_positional_arguments(first, last) 78 == (first, last) 79 ) 80 assert ( 81 # w_positional_arguments('last', 'first') 82 # == ('first', 'last') 83 # == ('last', 'first') 84 w_positional_arguments(last, first) 85 == (last, first) 86 ) 87 assert ( 88 w_positional_arguments(0, 1) 89 == (1, 0) 90 ) 91 92 93# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert (0, 1) == (1, 0)because the function always returns
first_input, last_inputand the call in this assertion sends0asfirst_inputand1aslast_input. Using substitutionw_positional_arguments(0 , 1 ) w_positional_arguments(first_input, last_input) return first_input, last_input return 0 , 1assert w_positional_arguments(0, 1) == (1, 0) assert (0, 1) == (1, 0)I change my expectation to match reality
74 assert ( 75 # w_positional_arguments('first', 'last') 76 # == ('first', 'last') 77 w_positional_arguments(first, last) 78 == (first, last) 79 ) 80 assert ( 81 # w_positional_arguments('last', 'first') 82 # == ('first', 'last') 83 # == ('last', 'first') 84 w_positional_arguments(last, first) 85 == (last, first) 86 ) 87 assert ( 88 w_positional_arguments(0, 1) 89 # == (1, 0) 90 == (0, 1) 91 ) 92 93 94# Exceptions seenthe test passes.
I add an assertion with a tuple (anything in parentheses
( )separated by a comma) and a list(anything in square brackets ‘[ ]’)74 assert ( 75 # w_positional_arguments('first', 'last') 76 # == ('first', 'last') 77 w_positional_arguments(first, last) 78 == (first, last) 79 ) 80 assert ( 81 # w_positional_arguments('last', 'first') 82 # == ('first', 'last') 83 # == ('last', 'first') 84 w_positional_arguments(last, first) 85 == (last, first) 86 ) 87 assert ( 88 w_positional_arguments(0, 1) 89 # == (1, 0) 90 == (0, 1) 91 ) 92 93 a_tuple = (1, 2, 3, 'n') 94 a_list = [1, 2, 3, 'n'] 95 assert ( 96 w_positional_arguments(a_list, a_tuple) 97 == (a_tuple, a_list) 98 ) 99 100 101# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: assert ([1, 2, 3, 'n...1, 2, 3, 'n')) == ((1, 2, 3, 'n...1, 2, 3, 'n'])because the function always returns
first_input, last_inputand the call in this test sends(1, 2, 3, 'n')asfirst_inputand[1, 2, 3, 'n']aslast_input. Using substitutiona_tuple = (1, 2, 3, 'n') a_list = [1, 2, 3, 'n']w_positional_arguments(a_list , a_tuple ) w_positional_arguments([1, 2, 3, 'n'], (1, 2, 3, 'n')) return first_input , last_input return [1, 2, 3, 'n'], (1, 2, 3, 'n')assert w_positional_arguments(a_list, a_tuple) == (a_tuple, a_list) assert ([1, 2, 3, 'n'], (1, 2, 3, 'n')) == ((1, 2, 3, 'n'), [1, 2, 3, 'n'])I change reality to match my expectation
93 a_tuple = (1, 2, 3, 'n') 94 a_list = [1, 2, 3, 'n'] 95 assert ( 96 # w_positional_arguments(a_list, a_tuple) 97 w_positional_arguments(a_tuple, a_list) 98 == (a_tuple, a_list) 99 ) 100 101 102# Exceptions seenthe test passes.
I remove the commented lines
61def test_w_positional_arguments(): 62 def w_positional_arguments(first_input, last_input): 63 return first_input, last_input 64 65 first, last = 'first', 'last' 66 67 assert ( 68 w_positional_arguments(first, last) 69 == (first, last) 70 ) 71 assert ( 72 w_positional_arguments(last, first) 73 == (last, first) 74 ) 75 assert ( 76 w_positional_arguments(0, 1) 77 == (0, 1) 78 ) 79 80 a_tuple = (1, 2, 3, 'n') 81 a_list = [1, 2, 3, 'n'] 82 assert ( 83 w_positional_arguments(a_tuple, a_list) 84 == (a_tuple, a_list) 85 ) 86 87 88# Exceptions seenI add a git commit message in the other terminal
git commit --all --message \ 'add test_w_positional_arguments'the terminal shows a summary of the changes then goes back to the command line.
test_w_keyword_arguments
The tests show that positional arguments must always be given in the right order. What if I forget the order? What if there are many inputs?
I can use `Keyword Arguments`_ to make sure the function always gets the values for the inputs it expects, that way it does what I want even when I send inputs out of order.
RED: make it fail
I go back to the terminal where the tests are running
I add a new test to
test_functions.py155 a_tuple = (1, 2, 3, 'n') 156 a_list = [1, 2, 3, 'n'] 157 reality = src.functions.w_positional_arguments( 158 a_tuple, a_list, 159 ) 160 my_expectation = (a_tuple, a_list) 161 self.assertEqual(reality, my_expectation) 162 163 def test_w_keyword_arguments(self): 164 reality = src.functions.w_keyword_arguments( 165 first_input='first', last_input='last', 166 ) 167 my_expectation = ('first', 'last') 168 self.assertEqual(reality, my_expectation) 169 170 171# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.functions' has no attribute 'w_keyword_arguments'because
functions.pyin thesrcfolder does not have a definition forw_keyword_arguments
GREEN: make it pass
I add a function definition to
functions.py26def w_positional_arguments(first_input, last_input): 27 return first_input, last_input 28 29 30def w_keyword_arguments(): 31 return Nonethe terminal is my friend, and shows TypeError
TypeError: w_keyword_arguments() got an unexpected keyword argument 'first_input'because the definition for
w_keyword_argumentsdoes not allow inputs and the test uses two in the call (first_inputandlast_input)I add the name of the unexpected argument_ in parentheses
30# def w_keyword_arguments(): 31def w_keyword_arguments(first_input): 32 return Nonethe terminal is my friend, and shows TypeError
TypeError: w_keyword_arguments() got an unexpected keyword argument 'last_input'. Did you mean 'first_input'?because the definition for
w_keyword_argumentsallows one input (first_input) and the test uses two in the call (first_inputandlast_input)I add a name for the second argument_ in parentheses
30# def w_keyword_arguments(): 31# def w_keyword_arguments(first_input): 32def w_keyword_arguments(first_input, second_input): 33 return Nonethe terminal is my friend, and shows TypeError
TypeError: w_keyword_arguments() got an unexpected keyword argument 'last_input'. Did you mean 'first_input'?because the definition for
w_keyword_argumentsallows two inputs with the namesfirst_inputandsecond_input, and the test calls the function withfirst_inputandlast_input, the names must match when I am using keyword argumentsI change the name of the second argument to match the name used in the call
30# def w_keyword_arguments(): 31# def w_keyword_arguments(first_input): 32# def w_keyword_arguments(first_input, second_input): 33def w_keyword_arguments(first_input, last_input): 34 return Nonethe terminal is my friend, and shows AssertionError
AssertionError: None != ('first', 'last')because the function returns None and the assertion expects
('first', 'last')I change the `return statement`_ to make the function return its inputs
30# def w_keyword_arguments(): 31# def w_keyword_arguments(first_input): 32# def w_keyword_arguments(first_input, second_input): 33def w_keyword_arguments(first_input, last_input): 34 # return None 35 return first_input, last_inputthe test passes.
REFACTOR: make it better
I remove the commented lines
26def w_positional_arguments(first_input, last_input): 27 return first_input, last_input 28 29 30def w_keyword_arguments(first_input, last_input): 31 return first_input, last_inputI add another assertion with the `keyword arguments`_ given out of order in test_w_keyword_arguments in
test_functions.py163 def test_w_keyword_arguments(self): 164 reality = src.functions.w_keyword_arguments( 165 first_input='first', last_input='last', 166 ) 167 my_expectation = ('first', 'last') 168 self.assertEqual(reality, my_expectation) 169 170 reality = src.functions.w_keyword_arguments( 171 last_input='last', first_input='first', 172 ) 173 my_expectation = ('last', 'first') 174 self.assertEqual(reality, my_expectation) 175 176 177# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: Tuples differ: ('first', 'last') != ('last', 'first')the order the function returns the values stayed the same this time, because it always returns
first_input, last_input.Compare this call that uses positional arguments and its result
src.functions.w_positional_arguments('last', 'first') ('last', 'first')with this call that uses keyword arguments and its result
src.functions.w_keyword_arguments( last_input='last', first_input='first', ) ('first', 'last')in both cases the function returns
first_input, last_inputI change
my_expectationto matchreality170 reality = src.functions.w_keyword_arguments( 171 last_input='last', first_input='first', 172 ) 173 # my_expectation = ('last', 'first') 174 my_expectation = ('first', 'last') 175 self.assertEqual(reality, my_expectation) 176 177 178# Exceptions seenthe test passes. The order does not matter when I use `keyword arguments`_.
I add variables to use them to remove repetition of
'first'and'last'from the test163 def test_w_keyword_arguments(self): 164 first, last = 'first', 'last' 165 166 reality = src.functions.w_keyword_arguments( 167 first_input='first', last_input='last', 168 ) 169 my_expectation = ('first', 'last') 170 self.assertEqual(reality, my_expectation)I use the new variables to remove repetition of
'first'and'last'from the test163 def test_w_keyword_arguments(self): 164 first, last = 'first', 'last' 165 166 reality = src.functions.w_keyword_arguments( 167 # first_input='first', last_input='last', 168 first_input=first, last_input=last, 169 ) 170 # my_expectation = ('first', 'last') 171 my_expectation = (first, last) 172 self.assertEqual(reality, my_expectation) 173 174 reality = src.functions.w_keyword_arguments( 175 # last_input='last', first_input='first', 176 last_input=last, first_input=first, 177 ) 178 # my_expectation = ('last', 'first') 179 # my_expectation = ('first', 'last') 180 my_expectation = (first, last) 181 self.assertEqual(reality, my_expectation) 182 183 184# Exceptions seenthe test is still green.
I can still call the function the same way I did in test_w_positional_arguments (without using the names). I add an assertion to show this
174 reality = src.functions.w_keyword_arguments( 175 # last_input='last', first_input='first', 176 last_input=last, first_input=first, 177 ) 178 # my_expectation = ('last', 'first') 179 # my_expectation = ('first', 'last') 180 my_expectation = (first, last) 181 self.assertEqual(reality, my_expectation) 182 183 reality = src.functions.w_keyword_arguments( 184 last, first, 185 ) 186 my_expectation = (first, last) 187 self.assertEqual(reality, my_expectation) 188 189 190# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: Tuples differ: ('last', 'first') != ('first', 'last')because the function uses the order (positions) when I do not use the names
I change
my_expectationto matchreality183 reality = src.functions.w_keyword_arguments( 184 last, first, 185 ) 186 # my_expectation = (first, last) 187 my_expectation = (last, first) 188 self.assertEqual(reality, my_expectation) 189 190 191# Exceptions seenthe test passes.
I add another assertion
183 reality = src.functions.w_keyword_arguments( 184 last, first, 185 ) 186 # my_expectation = (first, last) 187 my_expectation = (last, first) 188 self.assertEqual(reality, my_expectation) 189 190 zero, one = 0, 1 191 reality = src.functions.w_keyword_arguments( 192 last_input=zero, first_input=one, 193 ) 194 my_expectation = (zero, one) 195 self.assertEqual(reality, my_expectation) 196 197 198# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: Tuples differ: (1, 0) != (0, 1)I change
my_expectationto matchreality190 zero, one = 0, 1 191 reality = src.functions.w_keyword_arguments( 192 last_input=zero, first_input=one, 193 ) 194 # my_expectation = (zero, one) 195 my_expectation = (one, zero) 196 self.assertEqual(reality, my_expectation) 197 198 199# Exceptions seenthe test passes.
I add an assertion
190 zero, one = 0, 1 191 reality = src.functions.w_keyword_arguments( 192 last_input=zero, first_input=one, 193 ) 194 # my_expectation = (zero, one) 195 my_expectation = (one, zero) 196 self.assertEqual(reality, my_expectation) 197 198 a_set = {1, 2, 3, 'n'} 199 a_dictionary = {'key': 'value'} 200 reality = src.functions.w_keyword_arguments( 201 first_input=a_dictionary, 202 last_input=a_set, 203 ) 204 my_expectation = (a_set, a_dictionary) 205 self.assertEqual(reality, my_expectation) 206 207 208# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: Tuples differ: ({'key': 'value'}, {1, 2, 3, 'n'}) != ({1, 2, 3, 'n'}, {'key': 'value'})I change
realityto matchmy_expectation198 a_set = {1, 2, 3, 'n'} 199 a_dictionary = {'key': 'value'} 200 reality = src.functions.w_keyword_arguments( 201 # first_input=a_dictionary, 202 # last_input=a_set, 203 first_input=a_set, 204 last_input=a_dictionary, 205 ) 206 my_expectation = (a_set, a_dictionary) 207 self.assertEqual(reality, my_expectation) 208 209 210# Exceptions seenthe test passes.
w_keyword_argumentsandw_positional_argumentsare the same functions_, they alwaysreturn first_input, last_inputTheir names are different
def w_positional_arguments(first_input, last_input): def w_keyword_arguments(first_input, last_input):The difference that matters in the tests is how I call the functions_
I have to give the input in order when I use positional arguments
w_positional_arguments('first', 'last') return ('first', 'last')w_positional_arguments('last', 'first') return ('last', 'first')w_positional_arguments(0, 1) return (0, 1)w_positional_arguments((1, 2, 3, 'n'), [1, 2, 3, 'n']) return ((1, 2, 3, 'n'), [1, 2, 3, 'n'])w_keyword_arguments('last', 'first') return ('last', 'first')I can give the input in any order when I use `keyword arguments`_ because I use the names from the function definition when I call it
w_keyword_arguments( first_input='first', last_input='last', ) return ('first', 'last')w_keyword_arguments( last_input='last', first_input='first', ) return ('first', 'last')w_keyword_arguments(last_input=0, first_input=1,) return (1, 0)w_keyword_arguments( first_input={'key': 'value'}, last_input={1, 2, 3, 'n'}, ) return ({'key': 'value'}, {1, 2, 3, 'n'})
I add another assertion to show that the two functions are the same, by calling the
w_positional_argumentsfunction with keyword arguments198 a_set = {1, 2, 3, 'n'} 199 a_dictionary = {'key': 'value'} 200 reality = src.functions.w_keyword_arguments( 201 # first_input=a_dictionary, 202 # last_input=a_set, 203 first_input=a_set, 204 last_input=a_dictionary, 205 ) 206 my_expectation = (a_set, a_dictionary) 207 self.assertEqual(reality, my_expectation) 208 209 a_tuple = (1, 2, 3, 'n') 210 a_list = [1, 2, 3, 'n'] 211 reality = src.functions.w_positional_arguments( 212 first_input=a_tuple, 213 last_input=a_list, 214 ) 215 my_expectation = (a_list, a_tuple) 216 self.assertEqual(reality, my_expectation) 217 218 219# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: Tuples differ: ((1, 2, 3, 'n'), [1, 2, 3, 'n']) != ([1, 2, 3, 'n'], (1, 2, 3, 'n'))because these two calls are the same
src.functions.w_positional_arguments( first_input=a_tuple, last_input=a_list, ) src.functions.w_positional_arguments( a_tuple, a_list, )I change
realityto match myexpectation209 a_tuple = (1, 2, 3, 'n') 210 a_list = [1, 2, 3, 'n'] 211 reality = src.functions.w_positional_arguments( 212 # first_input=a_tuple, 213 # last_input=a_list, 214 first_input=a_list, 215 last_input=a_tuple, 216 ) 217 my_expectation = (a_list, a_tuple) 218 self.assertEqual(reality, my_expectation) 219 220 221# Exceptions seenthe test passes.
I remove the commented lines
163 def test_w_keyword_arguments(self): 164 first, last = 'first', 'last' 165 166 reality = src.functions.w_keyword_arguments( 167 first_input=first, last_input=last, 168 ) 169 my_expectation = (first, last) 170 self.assertEqual(reality, my_expectation) 171 172 reality = src.functions.w_keyword_arguments( 173 last_input=last, first_input=first, 174 ) 175 my_expectation = (first, last) 176 self.assertEqual(reality, my_expectation) 177 178 reality = src.functions.w_keyword_arguments( 179 last, first, 180 ) 181 my_expectation = (last, first) 182 self.assertEqual(reality, my_expectation) 183 184 zero, one = 0, 1 185 reality = src.functions.w_keyword_arguments( 186 last_input=zero, first_input=one, 187 ) 188 my_expectation = (one, zero) 189 self.assertEqual(reality, my_expectation) 190 191 a_set = {1, 2, 3, 'n'} 192 a_dictionary = {'key': 'value'} 193 reality = src.functions.w_keyword_arguments( 194 first_input=a_set, 195 last_input=a_dictionary, 196 ) 197 my_expectation = (a_set, a_dictionary) 198 self.assertEqual(reality, my_expectation) 199 200 a_tuple = (1, 2, 3, 'n') 201 a_list = [1, 2, 3, 'n'] 202 reality = src.functions.w_positional_arguments( 203 first_input=a_list, 204 last_input=a_tuple, 205 ) 206 my_expectation = (a_list, a_tuple) 207 self.assertEqual(reality, my_expectation) 208 209 210# Exceptions seenI add a git commit message in the other terminal
git commit --all --message \ 'add test_w_keyword_arguments'the terminal shows a summary of the changes then goes back to the command line.
test_w_args_and_kwargs
I can write functions_ that take both positional and keyword arguments, which is useful when I want some arguments to be required and some to be optional.
RED: make it fail
I go back to the terminal where the tests are running
I add a failing test to
test_functions.py200 a_tuple = (1, 2, 3, 'n') 201 a_list = [1, 2, 3, 'n'] 202 reality = src.functions.w_positional_arguments( 203 first_input=a_list, 204 last_input=a_tuple, 205 ) 206 my_expectation = (a_list, a_tuple) 207 self.assertEqual(reality, my_expectation) 208 209 def test_w_args_and_kwargs(self): 210 reality = ( 211 src.functions.w_args_and_kwargs( 212 last_input='last', 'first', 213 ) 214 ) 215 my_expectation = ('first', 'last') 216 self.assertEqual(reality, my_expectation) 217 218 219# Exceptions seenthe terminal is my friend, and shows SyntaxError
SyntaxError: positional argument follows keyword argumentbecause I cannot put keyword arguments before positional arguments. The Integrated Development Environment (IDE) also shows the error with a red squiggly line under
'first'.
GREEN: make it pass
I add SyntaxError to the list of Exceptions seen, in
test_functions.py217# Exceptions seen 218# AssertionError 219# NameError 220# AttributeError 221# TypeError 222# SyntaxErrorI change the order of the arguments to follow Python rules
209 def test_w_args_and_kwargs(self): 210 reality = ( 211 src.functions.w_args_and_kwargs( 212 # last_input='last', 'first', 213 'first', last_input='last', 214 ) 215 ) 216 my_expectation = ('first', 'last') 217 self.assertEqual(reality, my_expectation) 218 219 220# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.functions' has no attribute 'w_args_and_kwargs'because
functions.pydoes not have anything namedw_args_and_kwargsI add a function to
functions.py30def w_keyword_arguments(first_input, last_input): 31 return first_input, last_input 32 33 34def w_args_and_kwargs(): 35 return Nonethe terminal is my friend, and shows TypeError
TypeError: w_args_and_kwargs() got an unexpected keyword argument 'last_input'because the definition for
w_args_and_kwargsdoes not allow inputs and the test called the function with a keyword argument (last_input)I add the name to the function definition in parentheses, in
functions.py34# def w_args_and_kwargs(): 35def w_args_and_kwargs(last_input): 36 return Nonethe terminal is my friend, and shows TypeError
TypeError: w_args_and_kwargs() got multiple values for argument 'last_input'because the definition for
w_args_and_kwargstakes one argument, and the test calls the function with two arguments('first', last_input='last'). How does Python know which value to use forlast_inputif I use the position and the keyword?I add another name in parentheses to make it clearer
34# def w_args_and_kwargs(): 35# def w_args_and_kwargs(last_input): 36def w_args_and_kwargs(last_input, first_input): 37 return Nonethe terminal is my friend, and shows TypeError
TypeError: w_args_and_kwargs() got multiple values for argument 'last_input'because I have not fixed the problem, I gave confusing values in the call. Python still cannot tell the difference between the two values because I gave a positional value which according to the function definition is
last_inputand I gave a value with the namelast_input.How does it know what value to use for
last_input? The call tells it that the values forlast_inputare both'first'and'last', it would be like defining the function with the same name twice34# def w_args_and_kwargs(): 35# def w_args_and_kwargs(last_input): 36# def w_args_and_kwargs(last_input, first_input): 37def w_args_and_kwargs(last_input, last_input): 38 return Nonethe terminal is my friend, and shows SyntaxError
SyntaxError: duplicate argument 'last_input' in function definitionI change the names back and put them in the right order
34# def w_args_and_kwargs(): 35# def w_args_and_kwargs(last_input): 36# def w_args_and_kwargs(last_input, first_input): 37# def w_args_and_kwargs(last_input, last_input): 38def w_args_and_kwargs(first_input, last_input): 39 return Nonethe terminal is my friend, and shows AssertionError
AssertionError: None != ('first', 'last')because the function returns None and the assertion expects
('first', 'last')I change the `return statement`_ to give the test what it wants
34def w_args_and_kwargs(first_input, last_input): 35 return first_input, last_inputthe test passes.
I remove the commented lines
30def w_keyword_arguments(first_input, last_input): 31 return first_input, last_input 32 33 34def w_args_and_kwargs(first_input, last_input): 35 return first_input, last_inputI add variables to use them to remove the repetition of
'first'and'last'from test_w_args_and_kwargs intest_functions.py209 def test_w_args_and_kwargs(self): 210 first, last = 'first', 'last' 211 reality = ( 212 src.functions.w_args_and_kwargs( 213 # last_input='last', 'first', 214 'first', last_input='last', 215 ) 216 ) 217 my_expectation = ('first', 'last') 218 self.assertEqual(reality, my_expectation) 219 220 221# Exceptions seenI use the new variables to remove repetition of
'first'and'last'209 def test_w_args_and_kwargs(self): 210 first, last = 'first', 'last' 211 reality = ( 212 src.functions.w_args_and_kwargs( 213 # last_input='last', 'first', 214 # 'first', last_input='last', 215 first, last_input=last, 216 ) 217 ) 218 # my_expectation = ('first', 'last') 219 my_expectation = (first, last) 220 self.assertEqual(reality, my_expectation) 221 222 223# Exceptions seenthe test is still green.
I remove the commented lines
209 def test_w_args_and_kwargs(self): 210 first, last = 'first', 'last' 211 reality = ( 212 src.functions.w_args_and_kwargs( 213 first, last_input=last, 214 ) 215 ) 216 my_expectation = (first, last) 217 self.assertEqual(reality, my_expectation) 218 219 220# Exceptions seenI add a git commit message in the other terminal
git commit --all --message \ 'add test_w_args_and_kwargs'the terminal shows a summary of the changes then goes back to the command line.
test_w_optional_arguments
I can use positional and keyword arguments when I want some arguments to be required and some to be optional.
RED: make it fail
I go back to the terminal where the tests are running
I add a failing test to
test_functions.py209 def test_w_args_and_kwargs(self): 210 first, last = 'first', 'last' 211 reality = ( 212 src.functions.w_args_and_kwargs( 213 first, last_input=last, 214 ) 215 ) 216 my_expectation = (first, last) 217 self.assertEqual(reality, my_expectation) 218 219 def test_w_optional_arguments(self): 220 first_name, last_name = 'jane', 'doe' 221 reality = src.functions.w_optional_arguments( 222 first_name, last_input=last_name, 223 ) 224 my_expectation = (first_name, last_name) 225 self.assertEqual(reality, my_expectation) 226 227 228# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.functions' has no attribute 'w_optional_arguments'. Did you mean: 'w_positional_arguments'?because
functions.pydoes not have a definition forw_optional_arguments
GREEN: make it pass
I add a function named w_optional_arguments to functions.py
34 def w_args_and_kwargs(first_input, last_input):
35 return first_input, last_input
36
37
38 def w_optional_arguments(first_input, last_input):
39 return first_input, last_input
the test passes.
REFACTOR: make it better
I remove
last_input=last_namefrom the call tow_optional_argumentsintest_functions.py219 def test_w_optional_arguments(self): 220 first_name, last_name = 'jane', 'doe' 221 reality = src.functions.w_optional_arguments( 222 # first_name, last_input=last_name, 223 first_name, 224 ) 225 my_expectation = (first_name, last_name) 226 self.assertEqual(reality, my_expectation) 227 228 229# Exceptions seenthe terminal is my friend, and shows TypeError
TypeError: w_optional_arguments() missing 1 required positional argument: 'last_input'because the
last_inputargument MUST be given when this function is called (it is required).I make the argument optional by giving it a default value in
functions.py38# def w_optional_arguments(first_input, last_input): 39def w_optional_arguments(first_input, last_input='doe'): 40 return first_input, last_inputthe test passes since I do not need to give a value for the
last_inputparameter in the call tosrc.functions.w_optional_argumentsbecause the default value for thelast_inputparameter of the function isdoe. This means thatsrc.functions.w_optional_arguments('jane')is the same as
src.functions.w_optional_arguments('jane', last_input='doe')is the same as
return 'jane', 'doe'because
w_optional_argumentswill alwaysreturn first_input, last_inputA function uses the default value for a parameter when it is called without the parameter.
I remove the commented lines
I add another assertion to show that I can still call the function with different values, in test_w_optional_arguments in
test_functions.py219 def test_w_optional_arguments(self): 220 first_name, last_name = 'jane', 'doe' 221 reality = src.functions.w_optional_arguments( 222 # first_name, last_input=last_name, 223 first_name, 224 ) 225 my_expectation = (first_name, last_name) 226 self.assertEqual(reality, my_expectation) 227 228 first_name, blow = 'joe', 'blow' 229 reality = src.functions.w_optional_arguments( 230 first_name, blow, 231 ) 232 my_expectation = () 233 self.assertEqual(reality, my_expectation) 234 235 236# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: Tuples differ: ('joe', 'blow') != ()I change
my_expectationto matchreality228 first_name, blow = 'joe', 'blow' 229 reality = src.functions.w_optional_arguments( 230 first_name, blow, 231 ) 232 # my_expectation = () 233 my_expectation = (first_name, blow) 234 self.assertEqual(reality, my_expectation) 235 236 237# Exceptions seenthe test passes.
I add another assertion
228 first_name, blow = 'joe', 'blow' 229 reality = src.functions.w_optional_arguments( 230 first_name, blow, 231 ) 232 # my_expectation = () 233 my_expectation = (first_name, blow) 234 self.assertEqual(reality, my_expectation) 235 236 first_name = 'john' 237 reality = src.functions.w_optional_arguments( 238 first_input=first_name, 239 ) 240 my_expectation = () 241 self.assertEqual(reality, my_expectation) 242 243 244# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: Tuples differ: ('john', 'doe') != ()I change
my_expectationto matchreality236 first_name = 'john' 237 reality = src.functions.w_optional_arguments( 238 first_input=first_name, 239 ) 240 # my_expectation = () 241 my_expectation = (first_name, last_name) 242 self.assertEqual(reality, my_expectation) 243 244 245# Exceptions seenthe test passes since I do not need to give a value for the
last_inputparameter in the call tosrc.functions.w_optional_argumentsbecause the default value for thelast_inputparameter of thew_optional_argumentsfunction isdoe. This means thatsrc.functions.w_optional_arguments(first_input='john')is the same as
src.functions.w_optional_arguments( first_input='john', last_input='doe', )is the same as
return 'john', 'doe'because
w_optional_argumentswill alwaysreturn first_input, last_inputA function uses the default value for a parameter when it is called without the parameter.
I add one more assertion
236 first_name = 'john' 237 reality = src.functions.w_optional_arguments( 238 first_input=first_name, 239 ) 240 # my_expectation = () 241 my_expectation = (first_name, last_name) 242 self.assertEqual(reality, my_expectation) 243 244 last_name = 'smith' 245 reality = src.functions.w_optional_arguments( 246 last_input=last_name, 247 first_input=first_name, 248 ) 249 my_expectation = (last_name, first_name) 250 self.assertEqual(reality, my_expectation) 251 252 253# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: Tuples differ: ('john', 'smith') != ('smith', 'john')I change
my_expectationto matchreality244 last_name = 'smith' 245 reality = src.functions.w_optional_arguments( 246 last_input=last_name, 247 first_input=first_name, 248 ) 249 # my_expectation = (last_name, first_name) 250 my_expectation = (first_name, last_name) 251 self.assertEqual(reality, my_expectation) 252 253 254# Exceptions seenthe test passes.
I remove the commented lines
219 def test_w_optional_arguments(self): 220 first_name, last_name = 'jane', 'doe' 221 reality = src.functions.w_optional_arguments( 222 first_name, 223 ) 224 my_expectation = (first_name, last_name) 225 self.assertEqual(reality, my_expectation) 226 227 first_name, blow = 'joe', 'blow' 228 reality = src.functions.w_optional_arguments( 229 first_name, blow, 230 ) 231 my_expectation = (first_name, blow) 232 self.assertEqual(reality, my_expectation) 233 234 first_name = 'john' 235 reality = src.functions.w_optional_arguments( 236 first_input=first_name, 237 ) 238 my_expectation = (first_name, last_name) 239 self.assertEqual(reality, my_expectation) 240 241 last_name = 'smith' 242 reality = src.functions.w_optional_arguments( 243 last_input=last_name, 244 first_input=first_name, 245 ) 246 my_expectation = (first_name, last_name) 247 self.assertEqual(reality, my_expectation) 248 249 250# Exceptions seenI add a git commit message in the other terminal
git commit --all --message \ 'add test_w_optional_arguments'the terminal shows a summary of the changes then goes back to the command line.
Note
these four functions
w_keyword_argumentsw_positional_argumentsw_args_and_kwargsw_optional_arguments
are the same, they always return first_input, last_input, their names are different.
def w_positional_arguments(first_input, last_input):
def w_keyword_arguments(first_input, last_input):
def w_args_and_kwargs(first_input, last_input):
def w_optional_arguments(first_input, last_input='doe'):
first_input and last_input are also names (variables), they can be any names. The difference that matters in the tests is how I call the functions_
w_positional_arguments('first', 'last')
return 'first', 'last'
w_positional_arguments('last', 'first')
return 'last', 'first'
w_positional_arguments(
first_input=[1, 2, 3, 'n'], last_input=(1, 2, 3, 'n')
)
return [1, 2, 3, 'n'], (1, 2, 3, 'n')
w_keyword_arguments(first_input='first', last_input='last')
return 'first', 'last'
w_keyword_arguments(last_input='last', first_input='first')
return 'first', 'last'
w_keyword_arguments('last', 'first')
return 'last', 'first'
w_args_and_kwargs('first', last_input='last')
return 'first', 'last'
w_optional_arguments('jane', last_input='doe')
return 'jane', 'doe'
w_optional_arguments('jane')
return 'jane', 'doe'
w_optional_arguments('joe', 'blow')
return 'joe', 'blow'
w_optional_arguments(
first_input='john', last_input='smith'
)
return 'john', 'smith'
Tip
as a rule of thumb I use keyword arguments when I have 2 or more inputs so I do not have to remember the order.
test_w_unknown_arguments
I can make functions_ that take any number of positional and keyword arguments. This means I do not need to know how many inputs the function should take when it is called.
RED: make it fail
I go back to the terminal where the tests are running
I add a new test to
test_functions.py241 last_name = 'smith' 242 reality = src.functions.w_optional_arguments( 243 last_input=last_name, 244 first_input=first_name, 245 ) 246 my_expectation = (first_name, last_name) 247 self.assertEqual(reality, my_expectation) 248 249 def test_w_unknown_arguments(self): 250 reality = src.functions.w_unknown_arguments( 251 0, 1, a=2, b=3, 252 ) 253 my_expectation = None 254 self.assertEqual(reality, my_expectation) 255 256 257# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.functions' has no attribute 'w_unknown_arguments'. Did you mean: 'w_keyword_arguments'?because
functions.pydoes not havew_unknown_arguments
GREEN: make it pass
I add the function to
functions.py38def w_optional_arguments(first_input, last_input='doe'): 39 return first_input, last_input 40 41 42def w_unknown_arguments(): 43 return Nonethe terminal is my friend, and shows TypeError
TypeError: w_unknown_arguments() got an unexpected keyword argument 'a'I add the name to the function definition
42# def w_unknown_arguments(): 43def w_unknown_arguments(a): 44 return Nonethe terminal is my friend, and shows TypeError
TypeError: w_unknown_arguments() got multiple values for argument 'a'I had this same problem in test_w_args_and_kwargs. Python cannot tell if
ais a positional or keyword argument based on my function definition.
double starred expressions
Python has a way for a function to take any number of keyword arguments without knowing how many they are. I use it to replace
ain the parentheses42# def w_unknown_arguments(): 43# def w_unknown_arguments(a): 44def w_unknown_arguments(**kwargs): 45 return Nonethe terminal is my friend, and shows TypeError
TypeError: w_unknown_arguments() takes 0 positional arguments but 2 were givenI add a name for the first positional argument
42# def w_unknown_arguments(): 43# def w_unknown_arguments(a): 44# def w_unknown_arguments(**kwargs): 45def w_unknown_arguments(**kwargs, x): 46 return Nonethe terminal is my friend, and shows SyntaxError
SyntaxError: arguments cannot follow var-keyword argumenta reminder that I cannot put positional arguments after keyword arguments
I change the order of the inputs in
w_unknown_argumentsinfunctions.py42# def w_unknown_arguments(): 43# def w_unknown_arguments(a): 44# def w_unknown_arguments(**kwargs): 45# def w_unknown_arguments(**kwargs, x): 46def w_unknown_arguments(x, **kwargs): 47 return Nonethe terminal is my friend, and shows TypeError
TypeError: w_unknown_arguments() takes 1 positional argument but 4 were givenI add a name for the other positional argument
42# def w_unknown_arguments(): 43# def w_unknown_arguments(a): 44# def w_unknown_arguments(**kwargs): 45# def w_unknown_arguments(**kwargs, x): 46# def w_unknown_arguments(x, **kwargs): 47def w_unknown_arguments(x, y, **kwargs): 48 return Nonethe test passes.
REFACTOR: make it better
I add an assertion to see what happens if I call the function with 3 keyword arguments
249 def test_w_unknown_arguments(self): 250 reality = src.functions.w_unknown_arguments( 251 0, 1, a=2, b=3, 252 ) 253 my_expectation = None 254 self.assertEqual(reality, my_expectation) 255 256 reality = src.functions.w_unknown_arguments( 257 0, 1, a=2, b=3, c=4, 258 ) 259 my_expectation = () 260 self.assertEqual(reality, my_expectation) 261 262 263# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: None != ()I change
my_expectationto matchreality256 reality = src.functions.w_unknown_arguments( 257 0, 1, a=2, b=3, c=4, 258 ) 259 # my_expectation = () 260 my_expectation = None 261 self.assertEqual(reality, my_expectation) 262 263 264# Exceptions seenthe test passes because the function can take any number of keyword arguments without knowing how many are in the call.
I add an assertion to see what happens when I call the function with 3 positional arguments
206 reality = src.functions.w_unknown_arguments( 207 0, 1, a=2, b=3, c=4, 208 ) 209 my_expectation = None 210 self.assertEqual(reality, my_expectation) 211 212 reality = src.functions.w_unknown_arguments( 213 0, 1, 2, a=3, b=4, c=5, 214 ) 215 my_expectation = None 216 self.assertEqual(reality, my_expectation) 217 218 219# Exceptions seenthe terminal is my friend, and shows TypeError
TypeError: w_unknown_arguments() takes 2 positional arguments but 3 were giventhe function definition only allows two positional arguments
I change the definition of the
w_unknown_argumentsfunction to make it take three positional arguments42# def w_unknown_arguments(): 43# def w_unknown_arguments(a): 44# def w_unknown_arguments(**kwargs): 45# def w_unknown_arguments(**kwargs, x): 46# def w_unknown_arguments(x, **kwargs): 47# def w_unknown_arguments(x, y, **kwargs): 48def w_unknown_arguments(x, y, z, **kwargs): 49 return Nonethe terminal is my friend, and shows TypeError
TypeError: w_unknown_arguments() missing 1 required positional argument: 'z'because the previous assertion calls the function with two positional arguments and it now requires three.
starred expressions
Python also has a way to handle any number of positional arguments. I use it
42# def w_unknown_arguments(): 43# def w_unknown_arguments(a): 44# def w_unknown_arguments(**kwargs): 45# def w_unknown_arguments(**kwargs, x): 46# def w_unknown_arguments(x, **kwargs): 47# def w_unknown_arguments(x, y, **kwargs): 48# def w_unknown_arguments(x, y, z, **kwargs): 49def w_unknown_arguments(*args, **kwargs): 50 return Nonethe test passes.
*args, **kwargsis Python convention. I change the names to make it clearer42# def w_unknown_arguments(): 43# def w_unknown_arguments(a): 44# def w_unknown_arguments(**kwargs): 45# def w_unknown_arguments(**kwargs, x): 46# def w_unknown_arguments(x, **kwargs): 47# def w_unknown_arguments(x, y, **kwargs): 48# def w_unknown_arguments(x, y, z, **kwargs): 49# def w_unknown_arguments(*args, **kwargs): 50def w_unknown_arguments( 51 *positional_arguments, **keyword_arguments 52 ): 53 return NoneI change the `return statement`_ because I want the function to return its input (remember the identity function?)
50def w_unknown_arguments( 51 *positional_arguments, **keyword_arguments 52 ): 53 # return None 54 return positional_arguments, keyword_argumentsthe terminal is my friend, and shows
AssertionError: ((0, 1), {'a': 2, 'b': 3}) != NoneI get a tuple that has a tuple and a dictionary
I change
my_expectationto matchrealityin the first assertion249 def test_w_unknown_arguments(self): 250 reality = src.functions.w_unknown_arguments( 251 0, 1, a=2, b=3, 252 ) 253 # my_expectation = None 254 my_expectation = ((0, 1), {'a': 2, 'b': 3}) 255 self.assertEqual(reality, my_expectation)the terminal is my friend, and shows AssertionError
AssertionError: ((0, 1), {'a': 2, 'b': 3, 'c': 4}) != NoneI change
my_expectationto matchrealityin the second assertion249 def test_w_unknown_arguments(self): 250 reality = src.functions.w_unknown_arguments( 251 0, 1, a=2, b=3, 252 ) 253 # my_expectation = None 254 my_expectation = ((0, 1), {'a': 2, 'b': 3}) 255 self.assertEqual(reality, my_expectation) 256 257 reality = src.functions.w_unknown_arguments( 258 0, 1, a=2, b=3, c=4, 259 ) 260 # my_expectation = () 261 # my_expectation = None 262 my_expectation = ( 263 (0, 1), {'a': 2, 'b': 3, 'c': 4} 264 ) 265 self.assertEqual(reality, my_expectation)the terminal is my friend, and shows AssertionError
AssertionError: ((0, 1, 2), {'a': 3, 'b': 4, 'c': 5}) != NoneI change
my_expectationto matchrealityin the last assertion249 def test_w_unknown_arguments(self): 250 reality = src.functions.w_unknown_arguments( 251 0, 1, a=2, b=3, 252 ) 253 # my_expectation = None 254 my_expectation = ((0, 1), {'a': 2, 'b': 3}) 255 self.assertEqual(reality, my_expectation) 256 257 reality = src.functions.w_unknown_arguments( 258 0, 1, a=2, b=3, c=4, 259 ) 260 # my_expectation = () 261 # my_expectation = None 262 my_expectation = ( 263 (0, 1), {'a': 2, 'b': 3, 'c': 4} 264 ) 265 self.assertEqual(reality, my_expectation) 266 267 reality = src.functions.w_unknown_arguments( 268 0, 1, 2, a=3, b=4, c=5, 269 ) 270 # my_expectation = None 271 my_expectation = ( 272 (0, 1, 2), {'a': 3, 'b': 4, 'c': 5} 273 ) 274 self.assertEqual(reality, my_expectation) 275 276 277# Exceptions seenthe test passes.
I add variables to use them to remove repetition of the tuple and dictionary from the first assertion
249 def test_w_unknown_arguments(self): 250 a_tuple = (0, 1) 251 a_dictionary = {'a': 2, 'b': 3} 252 reality = src.functions.w_unknown_arguments( 253 0, 1, a=2, b=3, 254 ) 255 # my_expectation = None 256 my_expectation = ((0, 1), {'a': 2, 'b': 3}) 257 self.assertEqual(reality, my_expectation)I use the variables to remove repetition of the values
249 def test_w_unknown_arguments(self): 250 a_tuple = (0, 1) 251 a_dictionary = {'a': 2, 'b': 3} 252 reality = src.functions.w_unknown_arguments( 253 # 0, 1, a=2, b=3, 254 a_tuple, a_dictionary 255 ) 256 # my_expectation = None 257 # my_expectation = ((0, 1), {'a': 2, 'b': 3}) 258 my_expectation = (a_tuple, a_dictionary) 259 self.assertEqual(reality, my_expectation)the terminal is my friend, and shows AssertionError
AssertionError: Tuples differ: (((0, 1), {'a': 2, 'b': 3}), {}) != ((0, 1), {'a': 2, 'b': 3})because passing in the values this way means I am sending in two positional arguments -
(a_tuple, a_dictionary)so I get a tuple with a tuple of the arguments and an empty dictionary instead of a tuple with the arguments in the tuple I sent and a dictionary with the dictionary I sentI change the inputs with
*and**so that Python breaks up the contents, allowing them to be used as separate arguments249 def test_w_unknown_arguments(self): 250 a_tuple = (0, 1) 251 a_dictionary = {'a': 2, 'b': 3} 252 reality = src.functions.w_unknown_arguments( 253 # 0, 1, a=2, b=3, 254 # a_tuple, a_dictionary 255 *a_tuple, **a_dictionary 256 ) 257 # my_expectation = None 258 # my_expectation = ((0, 1), {'a': 2, 'b': 3}) 259 my_expectation = (a_tuple, a_dictionary) 260 self.assertEqual(reality, my_expectation)the test passes because
src.functions.w_unknown_arguments(*a_tuple, **a_dictionary)issrc.functions.w_unknown_arguments(0, 1, a=2, b=3).I add variables to the next assertion to use them to remove repetition of the tuple and dictionary from the second assertion
249 def test_w_unknown_arguments(self): 250 a_tuple = (0, 1) 251 a_dictionary = {'a': 2, 'b': 3} 252 reality = src.functions.w_unknown_arguments( 253 # 0, 1, a=2, b=3, 254 # a_tuple, a_dictionary 255 *a_tuple, **a_dictionary 256 ) 257 # my_expectation = None 258 # my_expectation = ((0, 1), {'a': 2, 'b': 3}) 259 my_expectation = (a_tuple, a_dictionary) 260 self.assertEqual(reality, my_expectation) 261 262 a_tuple = (0, 1) 263 a_dictionary = {'a': 2, 'b': 3, 'c': 4} 264 reality = src.functions.w_unknown_arguments( 265 0, 1, a=2, b=3, c=4, 266 ) 267 # my_expectation = () 268 # my_expectation = None 269 my_expectation = ( 270 (0, 1), {'a': 2, 'b': 3, 'c': 4} 271 ) 272 self.assertEqual(reality, my_expectation)I use the variables to remove repetition of the tuple and dictionary
262 a_tuple = (0, 1) 263 a_dictionary = {'a': 2, 'b': 3, 'c': 4} 264 reality = src.functions.w_unknown_arguments( 265 # 0, 1, a=2, b=3, c=4, 266 a_tuple, a_dictionary 267 ) 268 # my_expectation = () 269 # my_expectation = None 270 my_expectation = ( 271 # (0, 1), {'a': 2, 'b': 3, 'c': 4} 272 a_tuple, a_dictionary 273 ) 274 self.assertEqual(reality, my_expectation)the terminal is my friend, and shows AssertionError
AssertionError: Tuples differ: (((0, 1), {'a': 2, 'b': 3, 'c': 4}), {}) != ((0, 1), {'a': 2, 'b': 3, 'c': 4})because passing in the values this way means I am sending in two positional arguments -
(a_tuple, a_dictionary)so I get a tuple with a tuple of the arguments and an empty dictionary instead of a tuple with the arguments in the tuple I sent and a dictionary with the dictionary I sentI change the inputs with
*and**so that Python breaks up the contents, allowing them to be used as separate arguments262 a_tuple = (0, 1) 263 a_dictionary = {'a': 2, 'b': 3, 'c': 4} 264 reality = src.functions.w_unknown_arguments( 265 # 0, 1, a=2, b=3, c=4, 266 # a_tuple, a_dictionary 267 *a_tuple, **a_dictionary 268 ) 269 # my_expectation = () 270 # my_expectation = None 271 my_expectation = ( 272 # (0, 1), {'a': 2, 'b': 3, 'c': 4} 273 a_tuple, a_dictionary 274 ) 275 self.assertEqual(reality, my_expectation)the test passes because
src.functions.w_unknown_arguments(*a_tuple, **a_dictionary)issrc.functions.w_unknown_arguments(0, 1, a=2, b=3, c=4).I add variables to the third assertion to use them to remove repetition of the tuple and dictionary
249 def test_w_unknown_arguments(self): 250 a_tuple = (0, 1) 251 a_dictionary = {'a': 2, 'b': 3} 252 reality = src.functions.w_unknown_arguments( 253 # 0, 1, a=2, b=3, 254 # a_tuple, a_dictionary 255 *a_tuple, **a_dictionary 256 ) 257 # my_expectation = None 258 # my_expectation = ((0, 1), {'a': 2, 'b': 3}) 259 my_expectation = (a_tuple, a_dictionary) 260 self.assertEqual(reality, my_expectation) 261 262 a_tuple = (0, 1) 263 a_dictionary = {'a': 2, 'b': 3, 'c': 4} 264 reality = src.functions.w_unknown_arguments( 265 # 0, 1, a=2, b=3, c=4, 266 # a_tuple, a_dictionary 267 *a_tuple, **a_dictionary 268 ) 269 # my_expectation = () 270 # my_expectation = None 271 my_expectation = ( 272 # (0, 1), {'a': 2, 'b': 3, 'c': 4} 273 a_tuple, a_dictionary 274 ) 275 self.assertEqual(reality, my_expectation) 276 277 a_tuple = (0, 1, 2) 278 a_dictionary = {'a': 3, 'b': 4, 'c': 5} 279 reality = src.functions.w_unknown_arguments( 280 0, 1, 2, a=3, b=4, c=5, 281 ) 282 # my_expectation = None 283 my_expectation = ( 284 (0, 1, 2), {'a': 3, 'b': 4, 'c': 5} 285 ) 286 self.assertEqual(reality, my_expectation) 287 288 289# Exceptions seenI use the variables to remove repetition of the tuple and dictionary
277 a_tuple = (0, 1, 2) 278 a_dictionary = {'a': 3, 'b': 4, 'c': 5} 279 reality = src.functions.w_unknown_arguments( 280 # 0, 1, 2, a=3, b=4, c=5, 281 a_tuple, a_dictionary, 282 ) 283 # my_expectation = None 284 my_expectation = ( 285 # (0, 1, 2), {'a': 3, 'b': 4, 'c': 5} 286 a_tuple, a_dictionary 287 ) 288 self.assertEqual(reality, my_expectation) 289 290 291# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: Tuples differ: (((0, 1, 2), {'a': 3, 'b': 4, 'c': 5}), {}) != ((0, 1, 2), {'a': 3, 'b': 4, 'c': 5})because passing in the values this way means I am sending in two positional arguments -
(a_tuple, a_dictionary)so I get a tuple with a tuple of the arguments and an empty dictionary instead of a tuple with the arguments in the tuple I sent and a dictionary with the dictionary I sentI change the inputs with
*and**so that Python breaks up the contents, allowing them to be used as separate arguments277 a_tuple = (0, 1, 2) 278 a_dictionary = {'a': 3, 'b': 4, 'c': 5} 279 reality = src.functions.w_unknown_arguments( 280 # 0, 1, 2, a=3, b=4, c=5, 281 # a_tuple, a_dictionary, 282 *a_tuple, **a_dictionary, 283 ) 284 # my_expectation = None 285 my_expectation = ( 286 # (0, 1, 2), {'a': 3, 'b': 4, 'c': 5} 287 a_tuple, a_dictionary 288 ) 289 self.assertEqual(reality, my_expectation) 290 291 292# Exceptions seenthe test passes because
src.functions.w_unknown_arguments(*a_tuple, **a_dictionary)issrc.functions.w_unknown_arguments(0, 1, 2, a=3, b=4, c=5).
how Python reads positional arguments
I add an assertion to see what happens when I call w_unknown_arguments with ONLY positional arguments.
277 a_tuple = (0, 1, 2)
278 a_dictionary = {'a': 3, 'b': 4, 'c': 5}
279 reality = src.functions.w_unknown_arguments(
280 # 0, 1, 2, a=3, b=4, c=5,
281 # a_tuple, a_dictionary,
282 *a_tuple, **a_dictionary,
283 )
284 # my_expectation = None
285 my_expectation = (
286 # (0, 1, 2), {'a': 3, 'b': 4, 'c': 5}
287 a_tuple, a_dictionary
288 )
289 self.assertEqual(reality, my_expectation)
290
291 a_tuple = (0, 1, 2, 3)
292 reality = src.functions.w_unknown_arguments(
293 *a_tuple
294 )
295 my_expectation = ()
296 self.assertEqual(reality, my_expectation)
297
298
299 # Exceptions seen
the terminal is my friend, and shows AssertionError
AssertionError: Tuples differ: ((0, 1, 2, 3), {}) != ()
I change my_expectation to match reality
291 a_tuple = (0, 1, 2, 3)
292 reality = src.functions.w_unknown_arguments(
293 *a_tuple
294 )
295 # my_expectation = ()
296 my_expectation = (a_tuple, {})
297 self.assertEqual(reality, my_expectation)
298
299
300 # Exceptions seen
the test passes. The function gives me back the positional arguments in a tuple (things in parentheses (()) separated by commas) and gives me an empty dictionary (any key-value pairs in curly braces { } separated by a comma) for the keyword arguments because I did not give any in the call.
how Python reads keyword arguments
I add another assertion to see what happens when I call the function with ONLY keyword arguments
291 a_tuple = (0, 1, 2, 3)
292 reality = src.functions.w_unknown_arguments(
293 *a_tuple
294 )
295 # my_expectation = ()
296 my_expectation = (a_tuple, {})
297 self.assertEqual(reality, my_expectation)
298
299 a_dictionary = {'a': 4, 'b': 5, 'c': 6, 'd': 7}
300 reality = src.functions.w_unknown_arguments(
301 **a_dictionary
302 )
303 my_expectation = ()
304 self.assertEqual(reality, my_expectation)
305
306
307 # Exceptions seen
the terminal is my friend, and shows
AssertionError: Tuples differ:
((), {'a': 4, 'b': 5, 'c': 6, 'd': 7}) != ()
I change my_expectation to match reality
299 a_dictionary = {'a': 4, 'b': 5, 'c': 6, 'd': 7}
300 reality = src.functions.w_unknown_arguments(
301 **a_dictionary
302 )
303 # my_expectation = ()
304 my_expectation = ((), a_dictionary)
305 self.assertEqual(reality, my_expectation)
306
307
308 # Exceptions seen
the test passes. The function gives me back the positional arguments as an empty tuple (things in parentheses (()) separated by commas) because I did not give any in the call, it gives me a dictionary (any key-value pairs in curly braces { } separated by a comma) of the keyword arguments.
how Python reads positional and keyword arguments
I add one more assertion to see what happens when I call the function with no inputs
299 a_dictionary = {'a': 4, 'b': 5, 'c': 6, 'd': 7} 300 reality = src.functions.w_unknown_arguments( 301 **a_dictionary 302 ) 303 # my_expectation = () 304 my_expectation = ((), a_dictionary) 305 self.assertEqual(reality, my_expectation) 306 307 reality = src.functions.w_unknown_arguments() 308 my_expectation = TypeError 309 self.assertEqual(reality, my_expectation) 310 311 312# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: ((), {}) != <class 'TypeError'>I change the
my_expectationto matchreality307 reality = src.functions.w_unknown_arguments() 308 # my_expectation = TypeError 309 my_expectation = ((), {}) 310 self.assertEqual(reality, my_expectation) 311 312 313# Exceptions seenthe test passes.
I remove the commented lines
249 def test_w_unknown_arguments(self): 250 a_tuple = (0, 1) 251 a_dictionary = {'a': 2, 'b': 3} 252 reality = src.functions.w_unknown_arguments( 253 *a_tuple, **a_dictionary 254 ) 255 my_expectation = (a_tuple, a_dictionary) 256 self.assertEqual(reality, my_expectation) 257 258 a_tuple = (0, 1) 259 a_dictionary = {'a': 2, 'b': 3, 'c': 4} 260 reality = src.functions.w_unknown_arguments( 261 *a_tuple, **a_dictionary 262 ) 263 my_expectation = ( 264 a_tuple, a_dictionary 265 ) 266 self.assertEqual(reality, my_expectation) 267 268 a_tuple = (0, 1, 2) 269 a_dictionary = {'a': 3, 'b': 4, 'c': 5} 270 reality = src.functions.w_unknown_arguments( 271 *a_tuple, **a_dictionary, 272 ) 273 my_expectation = ( 274 a_tuple, a_dictionary 275 ) 276 self.assertEqual(reality, my_expectation) 277 278 a_tuple = (0, 1, 2, 3) 279 reality = src.functions.w_unknown_arguments( 280 *a_tuple 281 ) 282 my_expectation = (a_tuple, {}) 283 self.assertEqual(reality, my_expectation) 284 285 a_dictionary = {'a': 4, 'b': 5, 'c': 6, 'd': 7} 286 reality = src.functions.w_unknown_arguments( 287 **a_dictionary 288 ) 289 my_expectation = ((), a_dictionary) 290 self.assertEqual(reality, my_expectation) 291 292 reality = src.functions.w_unknown_arguments() 293 my_expectation = ((), {}) 294 self.assertEqual(reality, my_expectation) 295 296 297# Exceptions seenI remove the commented lines from the w_unknown_arguments function in
functions.py38def w_optional_arguments(first_input, last_input='doe'): 39 return first_input, last_input 40 41 42def w_unknown_arguments( 43 *positional_arguments, **keyword_arguments 44 ): 45 return positional_arguments, keyword_argumentsI add a git commit message in the other terminal
git commit --all --message \ 'add test_w_unknown_arguments'the terminal shows a summary of the changes then goes back to the command line.
Note
these statements are the same
w_unknown_arguments(0, 1, 2, 3, a=4, b=5, c=6, d=7)
w_unknown_arguments(
*(0, 1, 2, 3), **{'a': 4, 'b': 5, 'c': 6, 'd': 7}
)
because w_unknown_arguments in functions.py in the src folder will always
return positional_arguments, keyword_arguments
in this case
0, 1, 2, 3
*(0, 1, 2, 3)
are positional arguments which are taken as a tuple and
a=4, b=5, c=6, d=7
**{'a': 4, 'b': 5, 'c': 6, 'd': 7}
are keyword arguments which are taken as a dictionary.
The function reads positional arguments as tuples, and keyword arguments as dictionaries.
Is this why the update method of dictionaries can take a dictionary as input?
close the project
I close
test_functions.pyandfunctions.pyI click in the terminal where the tests are running
I use q on the keyboard to leave the tests. The terminal goes back to the command line.
I change directory to the parent of
functionscd ..the terminal shows
.../pumping_pythonI am back in the
pumping_pythondirectory
review
I ran tests to show that I can make functions_ with
the def, pass and return keywords
code from the chapter
what is next?
you have covered a bit so far and know
how to make a Python test driven development environment manually * what causes AssertionError? and * how to make functions
Would you like to use variables and functions to make a person?
rate pumping python
If this has been a 7 star experience for you, please CLICK HERE to leave a 5 star review of pumping python. It helps other people get into the book too.