2b. Prof. Rosenthal’s Review#
A review of Chapter 2: Variables and Statements, for students who have already studied the chapter. Use the two lists under Concepts covered as a checklist (click a list’s title to hide it), then work through the Questions, which go from easy to hard. Each question has a suggested answer under Answer. Try the question first, then open the Answer.
Concepts covered#
Python Syntax and Semantics
Variables and assignment
VARIABLE_NAME = EXPRESSIONcomputes the value of the expression and makes the variable refer to it. For example,n = 17creates the variablenwith the value17.The variable goes on the left of
=:17 = nis aSyntaxError.An assignment statement displays nothing.
A variable can be used anywhere its value can: in expressions and as a function argument. For example, after
n = 17,n + 25is42andprint(n)displays17.Assigning to an existing variable makes it refer to the new value. A variable computed from it earlier keeps its old value: after
x = 5,y = x + 1andx = 10,yis still6.NAME1 = NAME2 = EXPRESSIONassigns the same value to both variables.Using a variable that has not been assigned is a
NameError.
Variable names
A name can contain letters, digits and the underscore,
_, and cannot start with a digit. No spaces or other punctuation are allowed. For example,your_nameandscore2are legal;2nd_place,million!andmy scoreare aSyntaxError.By convention, variable names use only lowercase letters, with
_between words.Uppercase and lowercase letters are different:
Scoreandscoreare two different names.A keyword (a word such as
class,def,for,import,if,lambda,True,None) cannot be a variable name:class = 'Python'is aSyntaxError.int,floatandstrare not keywords, so they are legal variable names, but using them as names is a bad idea.
Importing modules
import MODULE_NAMEmakes a module’s variables and functions available asMODULE_NAME.NAME. For example, afterimport math,math.piis3.141592653589793.The math module provides
math.pi,math.e,math.sqrt(X)(square root),math.pow(X, Y)(X to the power Y),math.exp(X)(e to the power X),math.sin(X)andmath.cos(X). These functions return floats:math.sqrt(25)is5.0andmath.pow(5, 2)is25.0.X ** Yalso raises X to the power Y, and is used more often thanmath.pow. With two integers it produces an integer:5 ** 2is25.Importing a module that does not exist, such as
import maath, is aModuleNotFoundError.Using
math.piwithout first runningimport mathis aNameError.
Expressions, statements and display
An expression (a value, a variable, a function call, or a combination of these with operators) has a value. A statement (such as an assignment or an import) has an effect but no value.
In a notebook cell, only the value of the last expression is displayed.
print(VALUE1, VALUE2, ...)displays any number of values on one line, separated by spaces. For example,print('The answer is', 42)displaysThe answer is 42.Each call to
printdisplays a new line.printdisplays strings without their quotes.
Function arguments
Some functions take one argument, like
len(STRING); some take two, likemath.pow(X, Y); some take any number, likeprint.Some arguments are optional.
int(STRING, BASE)reads the string as a number in that base:int('101', 2)is5.round(NUMBER, DIGITS)rounds to that many decimal places:round(3.14159, 3)is3.142.Calling a function with too many arguments, too few arguments, or an argument of the wrong type is a
TypeError. For example,math.pow(2)andmath.sqrt('123')are each aTypeError.
Comments
#starts a comment: Python ignores everything from the#to the end of the line. A comment can be on its own line or at the end of a line of code.A
#inside a string is part of the string, not a comment:print('a # b')displaysa # b.
Errors
If a cell has a syntax error anywhere, none of its code runs: Python displays the error immediately.
A runtime error stops the program at the line where it happens; the lines before it have already run.
Definitions, etc.
Definitions
DEFINITION: A variable is a name that refers to a value.
DEFINITION: An assignment statement is a statement that assigns a value to a variable.
DEFINITION: A state diagram shows a set of variables, each name with an arrow pointing to its value.
DEFINITION: A keyword is a special word used to specify the structure of a program.
DEFINITION: A module is a file that contains Python code, such as variables and function definitions.
DEFINITION: An import statement is a statement that reads a module so its variables and functions can be used.
DEFINITION: The dot operator,
., is used to get a variable or function from a module, as inmath.sqrt.DEFINITION: To evaluate an expression is to compute its value.
DEFINITION: A statement is a unit of code that has an effect but no value, such as an assignment or an import.
DEFINITION: To execute a statement is to run it and do what it says.
DEFINITION: An argument is a value given to a function when it is called.
DEFINITION: A comment is text in a program that explains the program and has no effect on how it runs.
DEFINITION: A syntax error is an error in the structure of a program.
DEFINITION: A runtime error is an error that makes a running program display an error message and stop.
DEFINITION: An exception is an error detected while the program is running (another name for a runtime error).
DEFINITION: A semantic error is an error that makes a program do the wrong thing without displaying an error message.
Other ideas
Comments are most useful when they explain what is not obvious from the code, especially why the code does something. A comment that repeats what the code says is useless.
Good variable names reduce the need for comments, but very long names make expressions hard to read.
Knowing which kind of error you have (syntax, runtime or semantic) helps you find it faster.
When you learn a new feature, make mistakes on purpose to learn what the error messages mean.
Questions#
All the questions use only variables, arithmetic, strings, print and the math module.
The setup cell below imports math.
import math
Question 1 (easy): what is displayed?#
Predict what this code displays, then open the Answer to check.
x = 8
y = 2
print(x + y, x * y)
print(x / y)
print(x ** y)
Answer
10 16
4.0
64
print(x + y, x * y) displays two values on one line, separated by a space.
/ always produces a float, so 8 / 2 is 4.0. ** is exponentiation: 8 ** 2 is 64.
Question 2 (easy): what is displayed?#
name = 'Ada'
age = 36
print('Name:', name)
print(name, 'is', age, 'years old')
print('name')
Answer
Name: Ada
Ada is 36 years old
name
Without quotes, name is a variable, and print displays its value, Ada.
With quotes, 'name' is a string, and print displays the string itself (without the quotes).
Question 3 (easy): what is displayed?#
word = 'ha'
laugh = word * 3
print(laugh, len(laugh))
print(word + '!' + word)
Answer
hahaha 6
ha!ha
word * 3 makes 3 copies of 'ha' joined together, and len counts its 6 letters.
+ joins strings.
Question 4 (easy): what is displayed?#
What does this code display when it is run as a notebook cell?
price = 4
price * 2
price * 3
Answer
12
12, and nothing else.
In a notebook cell, only the value of the last expression is displayed.
price * 2 is computed, but its value, 8, is not displayed. To display both values, use print:
price = 4
print(price * 2)
print(price * 3)
8
12
Question 5 (medium): what is displayed?#
x = 5
y = x + 1
x = 10
print(x, y)
Answer
10 6
y = x + 1 computes 5 + 1 and makes y refer to 6.
Assigning a new value to x afterwards does not change y: y refers to a value, not to the expression that computed it.
Question 6 (medium): what is displayed?#
# print('one')
print('two') # print('three')
print('four # five')
Answer
two
four # five
The first line is a comment, so it does nothing.
On the second line, everything from # to the end of the line is a comment, so only print('two') runs.
On the third line the # is inside a string, so it is part of the string, not the start of a comment.
Question 7 (medium): what is displayed?#
import math
print(math.sqrt(16))
print(math.pow(2, 3))
print(2 ** 3)
print(round(math.pi, 2))
Answer
4.0
8.0
8
3.14
The math functions return floats, even when the result is a whole number, so math.sqrt(16) is 4.0 and math.pow(2, 3) is 8.0.
** with two integers produces an integer.
The optional second argument of round is the number of decimal places.
Question 8 (medium): what is displayed?#
print(int('101', 2))
print(int('11', 2) + int('11'))
print(round(2.71828, 1), round(2.71828))
Answer
5
14
2.7 3
The optional second argument of int is the base: '101' in base 2 is 4 + 0 + 1 = 5, and '11' in base 2 is 2 + 1 = 3.
Without it, int('11') is eleven, so the second line is 3 + 11 = 14.
Without its second argument, round rounds to the nearest integer.
Question 9 (medium): legal and illegal names#
For each part, predict whether it runs or causes an error. If it runs, what does it display?
Part a
my_score = 10
print(my_score)
Part b
2nd_place = 'Bo'
Part c
total-cost = 5
Part d
lambda = 0.5
Part e
Lambda = 0.5
print(Lambda)
Answer
Part a: It runs and displays:
10
Letters, digits and _ are allowed in names.
Part b: A name cannot start with a digit (a SyntaxError):
2nd_place = 'Bo'
^
SyntaxError: invalid decimal literal
Part c: - is not allowed in a name (the only punctuation allowed is _). Python reads total-cost as total minus cost, which cannot be assigned to (a SyntaxError):
total-cost = 5
^
SyntaxError: cannot assign to expression here. Maybe you meant '==' instead of '='?
Part d: lambda is a keyword, so it cannot be a variable name (a SyntaxError):
lambda = 0.5
^
SyntaxError: invalid syntax
Part e: It runs and displays:
0.5
Uppercase and lowercase letters are different, so Lambda is not the keyword lambda.
It is legal, but by convention variable names use only lowercase letters.
Question 10 (medium): wrong calls#
math.pow(X, Y) raises X to the power Y. Two correct ways to call it:
import math
print(math.pow(5, 2))
25.0
import math
print(math.pow(2, 0.5))
1.4142135623730951
Each of the next three calls is wrong in a different way. Predict the error for each, then open the Answer to check.
Part a
import math
math.pow(2)
Part b
import math
math.pow(2, 3, 4)
Part c
import math
math.pow('2', 3)
Answer
Part a: Too few arguments (a TypeError):
1 import math
----> 2 math.pow(2)
TypeError: pow expected 2 arguments, got 1
Part b: Too many arguments (a TypeError):
1 import math
----> 2 math.pow(2, 3, 4)
TypeError: pow expected 2 arguments, got 3
Part c: '2' is a string, not a number. Its quotes make it a string even though it contains a digit (a TypeError):
1 import math
----> 2 math.pow('2', 3)
TypeError: must be real number, not str
All three are a TypeError. Use math.pow(2, 3) (or 2 ** 3) instead.
Question 11 (medium): write code#
The variables hours, minutes and seconds have already been assigned.
Write code that computes the total number of seconds, assigns it to a variable called total, and displays it.
Examples (each example assigns the variables; your code comes after them)
Run this cell to assign hours, minutes and seconds.
hours = 1
minutes = 2
seconds = 3
3723
hours = 0
minutes = 42
seconds = 42
2562
Answer
total = hours * 60 * 60 + minutes * 60 + seconds
print(total)
An hour has 60 * 60 seconds and a minute has 60. Multiplication happens before addition, so no parentheses are needed.
Another approach: give the conversion factors names, so the code explains itself:
seconds_per_minute = 60
seconds_per_hour = 60 * seconds_per_minute
total = hours * seconds_per_hour + minutes * seconds_per_minute + seconds
print(total)
Question 12 (medium): write code with comments#
The variable km holds a distance in kilometers.
Write code that displays the distance in miles, rounded to 2 decimal places, in the form shown below.
A mile is 1.61 kilometers. Add a comment that says where the number 1.61 comes from.
Examples
Run this cell to assign km.
km = 10
10 km is 6.21 miles
km = 42.195
42.195 km is 26.21 miles
Answer
miles = km / 1.61 # one mile is about 1.61 kilometers
print(km, 'km is', round(miles, 2), 'miles')
The comment explains something that is not obvious from the code.
A comment like # divide km by 1.61 would only repeat what the code says.
Another approach: give the number a name, which also documents it:
km_per_mile = 1.61 # one mile is about 1.61 kilometers
print(km, 'km is', round(km / km_per_mile, 2), 'miles')
Question 13 (hard): what is displayed?#
a = 3
b = 5
a = a + b
b = a - b
a = a - b
print(a, b)
Answer
5 3
Follow the values one line at a time:
a = a + bmakesarefer to3 + 5, which is8(bis still5).b = a - bmakesbrefer to8 - 5, which is3.a = a - bmakesarefer to8 - 3, which is5.
The code swaps the values of a and b. On the right side of =, each variable has the value it got from the most recent assignment.
Question 14 (hard): syntax errors and runtime errors#
Each part has an error on its second line. Predict what each part displays before the error, and which error it shows.
Part a
print('start')
import maath
print('end')
Part b
print('start')
my score = 10
print('end')
Answer
Part a: The first line runs, then the program stops at the runtime error, so end is never displayed (a ModuleNotFoundError):
start
1 print('start')
----> 2 import maath
3 print('end')
ModuleNotFoundError: No module named 'maath'
Part b: Nothing is displayed except the error, not even start (a SyntaxError):
my score = 10
^
SyntaxError: invalid syntax
A syntax error (here, a space in a name) is found before any of the code runs, so none of it runs. A runtime error happens while the code runs, so the lines before it have already run.
Question 15 (hard): find the error#
This code should display the average of three test scores, which is 80.0.
What does it display instead? What kind of error is it (syntax, runtime or semantic), and how do you fix it?
score1 = 90
score2 = 80
score3 = 70
average = score1 + score2 + score3 / 3
print(average)
Answer
193.33333333333334
Division happens before addition, so only score3 is divided by 3: 90 + 80 + 23.333333333333332.
It is a semantic error: the code runs without an error message, but does not do what was intended.
Fix it with parentheses:
average = (score1 + score2 + score3) / 3
print(average)
80.0
Question 16 (hard): write code#
The variables price and quantity hold strings, as if a user had typed them, for example price = '19.99'.
Write code that displays the total cost, price times quantity, rounded to 2 decimal places, in the form shown below.
Examples
Run this cell to assign price and quantity.
price = '19.99'
quantity = '3'
Total: 59.97
price = '2.5'
quantity = '4'
Total: 10.0
Answer
Convert the strings to numbers first:
total = float(price) * int(quantity)
print('Total:', round(total, 2))
Without the conversions, price * quantity is a TypeError (a string cannot be multiplied by a string),
and price * 3 would make 3 copies of the string: '19.9919.9919.99'.
round is needed because floating-point arithmetic is not exact: with price = '0.1' and quantity = '3', the total is 0.30000000000000004 before rounding.
float(quantity) also works, for quantities like '1.5' (kilograms, for example).
Question 17 (hard): write code#
The variable total holds a number of seconds (a whole number).
Write code that displays it as hours, minutes and seconds, in the form shown below.
Use integer division, //, which divides and rounds down to an integer (for example, 7 // 2 is 3).
Examples
Run this cell to assign total.
total = 3725
1 h 2 min 5 s
total = 7384
2 h 3 min 4 s
Answer
Take out the whole hours first, then the whole minutes from what is left:
hours = total // 3600 # 3600 seconds in an hour
rest = total - hours * 3600 # seconds left after the whole hours
minutes = rest // 60
seconds = rest - minutes * 60
print(hours, 'h', minutes, 'min', seconds, 's')
Another approach computes the minutes from the total first:
total_minutes = total // 60
seconds = total - total_minutes * 60
hours = total_minutes // 60
minutes = total_minutes - hours * 60
print(hours, 'h', minutes, 'min', seconds, 's')
By the way: Python also has an operator, %, that computes the remainder of a division directly (3725 % 3600 is 125), which makes this shorter.
Summary and questions by Prof. Y. Rosenthal, based on Think Python: 3rd Edition by Allen B. Downey. Text license: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International