1.3.4.A.AK NestedBranchingAndInput
1.3.4.A.AK NestedBranchingAndInput
1.3.4.A.AK NestedBranchingAndInput
Procedure
1. Form pairs as directed by your teacher. Meet or greet each other to practice
professional skills. Launch Canopy and open an editor window. Set the working
directory for the IPython session and turn on session logging. Open a new file in
the code editor and save it as JDoeJSmith_1_3_4.py.
In []: %logstart -ort studentName_1_3_4.log
In []: # Jane Doe John Smith 1.3.4 IPython log
1 def food_id(food):
2 ''' Returns categorization of food
3
4 food is a string
5 returns a string of categories
6 '''
7 # The data
8 fruits = ['apple', 'banana', 'orange']
9 citrus = ['orange']
10 starchy = ['banana', 'potato']
11
12 # Check the category and report
13 if food in fruits:
14 if food in citrus:
15 return 'Citrus, Fruit'
16 else:
17 return 'NOT Citrus, Fruit'
18 else:
19 if food in starchy:
20 return 'Starchy, NOT Fruit'
21 else:
22 return 'NOT Starchy, NOT Fruit'
b. Every input will cause only one of the following lines of code to be executed.
i. What input will cause line 15 to be executed?
food_id('orange')
ii. What input will cause line 17 to be executed?
food_id('apple')
iii. What input will cause line 20 to be executed?
food_id('potato')
iv. What input will cause line 22 to be executed? Answers vary
food_id('random string')
food_id(4)
food_id('fish')
c. Bananas are starchy, and the program "knows" it. Explain why line 20 will
never result in bananas being reported as starchy.
3. The example in the previous step shows one reason bugs can be difficult to track
down. Just the job of getting the program to “fall into” all the blocks of code can
be difficult, and bugs can hide for years in a rarely executed line of code in a large
program. To create code with fewer bugs, developers use glass box testing.
That means they create a test suite that will run through every block of code.
Some programmers write their test suite first, an approach called test-driven
design or Extreme Programming (XP).
24 def food_id_test_AK():
25 ''' Unit test for food_id
26 returns True if good, returns False and prints error if not
27 good
28 '''
29 works = True
30 if food_id('orange') != 'Citrus, Fruit':
31 works = False
32 print('orange bug in food id()')
33 if food_id('banana') != 'NOT Citrus, Fruit':
34 works = False
35 print('banana bug in food_id()')
36 # Add tests so that all lines of code are visited during test
37 if food_id('potato') != 'Starchy, NOT Fruit':
38 works = False
39 print('potato bug in food_id()')
40 if food_id('fish') != 'NOT Starchy, NOT Fruit':
41 works = False
42 print('fish bug in food_id()')
43 if works:
44 print('food_id passed all tests!')
45 return works
4. Define a function f(x) that implements this flow chart. A flow chart is another
way to represent an algorithm; input and output are in rectangles, and
branching decisions are in diamonds. The exercise illustrates the % operator,
which identifies the remainder after division. As an example, 13 % 4 is 1, since
13÷ 4 is 3 remainder 1.
In []: f(12)
5. What set of test cases could you use to visit all the code? You need four numbers:
a non-integer, any odd number, any multiple of 6, and any even number that is
not a multiple of 6. For example: 1.5, 7, 12, and 10
Part II: The raw_input() function, type casting, and print() from Python 3
6. To get input from the user of a program, we normally use a graphical user
interface (GUI). That is the subject of Lesson 1.3. Beginners often want a
simple way to obtain text input. Python uses the raw_input(prompt)
command. It has some annoying behavior that we have to deal with for now — it
always returns a string even when numeric type is appropriate. In addition
IPython ignores Ctrl-C interrupts with raw_input(), so infinite loops will require
restarting the Python kernel. Finally the prompt doesn't appear until the user
starts typing. That said, here’s how you use it:
In []: a = raw_input('Give me a number between 5 and 6: ')
Give me a number between 5 and 6: 5.5
Even though the user typed a number, raw_input() returned a string. You can
see that as follows.
In []: a
Out[]: u'5.5'
In []: type(a)
Out[]: unicode
The variable a has a variable type that is a string. Keyboard input might be
encoded as a unicode type, as shown above, or as a str type, but either way, it is
a string of characters. (Unicode is a set of characters that includes all of the
world’s written languages. It is encoded with UTF-8, an extension of ASCII. The u
in u'5' indicates that the string returned by the raw_input() command is a
Unicode string.)
To use numeric values from the input, you have to turn the string into an int or a
float. This will raise an error if the user didn’t provide an int or a float.
There are commands – not covered in this course – that catch the error so that
it doesn’t continue up to the Python interpreter and halt the program. For now,
however, we can live with an error if the user does something unexpected.
To convert from a string to a number, you can use the int() function or the
float() function. Forcing a value to be converted to a particular type is called
type casting. Continuing from a being '5.5' above,
In []: int(a)
ValueError: invalid literal for int() with base 10: '5.5'
In []: float(a)
In []: int(float(a))
Out[]: 5
You can also type cast a number into a string:
In []: b = 6
In []: a + b
TypeError: cannot concatenate 'str' and 'int' objects
In []: a + str(b)
Out[]: '5.56'
In []: float(a) + b
Out[]: 11.5
Explain the difference between + as concatenation and + as numeric addition.
When the + operator is between two strings, it concatenates, putting the second
string of characters right after the first string of characters and into a single
concatenated string. When the + operator is between two numbers, it performs
numeric addition, resulting in an int or float.
In []: guess_once()
I have a number between 1 and 4 inclusive.
Guess: 3
Right, my number is 3!
In []: guess_once()
I have a number between 1 and 4 inclusive.
Guess: 3
Wrong, my number is 4.
In []: guess_once()
I have a number between 1 and 4 inclusive.
Guess: 3
Too high, my number was 2!
In []: guess_once()
I have a number between 1 and 4 inclusive.
Guess: 1
Right on! I was number 1!
See guess_once_AK.py.
8. Create a function quiz_decimal(low, high) that asks the user for a number
between low and high and tells them whether they succeeded.
In []: quiz_decimal(4, 4.1)
Type a number between 4 and 4.1:
4.5
No, 4.5 is greater than 4.1
Conclusion
1. What is the relationship between if-structures and glass box testing?
Answers vary. To throughly test code, it is necessary to execute all lines of the
code at least once. With if-else structures, it helps if you can see the conditionals
and make sure that both the if block and else block are executed. Glass box
2. Nested if-else structures can contain many blocks of code. How many of those
blocks of code might be executed?
An if-elif-elif-else structure will always execute 1 block of code. An if-elif-elif (i.e.,
without the else) structure might execute 0 or 1 blocks of code. If the structure
has nested conditions, several blocks of code might execute:
if a:
block1
if b:
block2
else:
block3
block5
else:
block6
Here, there might be one block of code (only block6 if a is False) or three blocks
of code (block1, block5, and either block2 or block3 if a is True).
3. What does a test suite do, and why do you think programmers often write test
suites first, before they've even written the functions that will be tested?
Explanations vary. Example: A test suite runs other code several times, providing
different input or arguments, to make sure that the code will work as expected for
specific test cases that cover a range of possibilities – a range so that all lines of
code get tested.