Weeks
Intro to PythonWeek 2 · Strings, Conditionals and Modules
Week 2 Notes

Python,
Week 2

Meaningful names, string methods, conditionals and your first modules: where Python code starts to look like real programs.

7 chapters41 worked examples~44 min read
Stringsif / elif / elseCaesar cipherModules

Chapters

  1. 01Variables: Names, Comments and TypingPart 1
  2. 02Operators and Strings: Membership, Chaining, Escapes, QuotesPart 2
  3. 03String Methods and the Caesar CipherPart 3
  4. 04Conditional StatementsPart 4
  5. 05Practice ZonePart 5
  6. 06Importing Modules: math, random, calendarPart 6
  7. 07Week 2 Summary SheetAll parts
01
Basics

Variables: Names, Comments and Typing

How to name variables, document code, assign several names at once and update values with short-hand operators.

1.1Meaningful variable names

Programmers write variables all the time, so a name that describes the stored information makes a program easier to read. Names such as a, b or x are fine for a tiny calculation, but they hide what the value means.

Hard to read
Python
a = "Ayush"
b = 18
print(a)
print(b)
Output
Ayush
18
Easy to read
Python
name = "Ayush"
age = 18
print(name)
print(age)
Output
Ayush
18
Exam idea

Meaningful names improve readability and make the purpose of a variable clear. The output is the same; only the human reading it benefits.

1.2Comments

Comments explain code to other people. A # starts a single-line comment; Python ignores everything after it on that line.

Python
name = "Ayush"
# This variable stores my name
age = 18
# This variable stores my age
print(name)
print(age)
Output
Ayush
18
  • # starts a single-line comment.
  • Comments are ignored during execution.
  • Their purpose is explanation and understanding.
Python
x = 5  # a comment can follow code on the same line
# print("this line never runs")
print(x)
Output
5

1.3Dynamic typing

Python is a dynamically typed language: a variable can refer to values of different types at different points of the run. You never declare a type before assigning.

Python
thing = "Hello World"
print(type(thing))
thing = 12
print(type(thing))
Output
<class 'str'>
<class 'int'>
thing"Hello World"<class 'str'>Step 1thing12<class 'int'>Step 2the name does not carry a type; the value it points to does
Figure 1. The name thing first points to a string, later to an integer
Key point. The type belongs to the value, not to the name. The name is just a label you can move to another value.

1.4Rules for variable names

  • Start with a letter or underscore (_); never with a digit.
  • Names are case-sensitive: age and Age are different.
  • Only letters, digits and underscores are allowed.
  • It must not be a keyword (and, or, not, for, if, else, while, ...).
NameValid?Why
student_namevalidletters and underscore
_agevalidmay start with an underscore
marks2validdigit is fine after the first character
2nd_placeinvalidstarts with a digit
first-nameinvalid- is not allowed
forinvalidreserved keyword
Python
student_name = "A"
_age = 20
marks2 = 95
print(student_name, _age, marks2)
Output
A 20 95
Python
age = 18
print(Age)
Error
NameError: name 'Age' is not defined

The last block shows case-sensitivity: Age was never created, so Python raises a NameError.

1.5Multiple assignment and unpacking

Python
x, y = 1, 2
print(x, y)
Output
1 2
Python
x = y = z = 8
print(x, y, z)
Output
8 8 8

x, y = 1, 2 gives each name its own value; x = y = z = 8 gives all the names the same value. Values taken from a collection can be unpacked into several names:

Python
a, b, c = (100, 200, 300)
print(a)
print(b)
print(c)
print(type(a), type(b))
Output
100
200
300
<class 'int'> <class 'int'>
names and values matcha100b200c300a, b, c = 100, 200, 300counts differa, b = 1, 2, 3ValueError3 names need exactly 3 values
Figure 2. Unpacking needs as many names as values
Python
a, b = 1, 2, 3
Error
ValueError: too many values to unpack (expected 2, got 3)
Important. The number of names and values must match, otherwise Python raises ValueError.

1.6Deleting a variable

Python
x = 3
print(x)
del x
print(x)
Error
3
NameError: name 'x' is not defined

After del x the name no longer exists, so using it raises a NameError. (The source shows the last print as a comment for this reason.)

1.7Short-hand assignment operators

OperatorExampleEquivalent
+=x += 3x = x + 3
-=x -= 3x = x - 3
*=x *= 3x = x * 3
/=x /= 3x = x / 3
%=x %= 3x = x % 3
//=x //= 3x = x // 3
**=x **= 3x = x ** 3
Python
x = 10
x += 3
print("+= ", x)
x -= 2
print("-= ", x)
x *= 2
print("*= ", x)
x /= 2
print("/= ", x)
x %= 3
print("%= ", x)
x //= 2
print("//= ", x)
x **= 3
print("**= ", x)
Output
+=  13
-=  11
*=  22
/=  11.0
%=  2.0
//=  1.0
**=  1.0
Watch the type

After x /= 2 the value becomes a float (11.0), so every later step stays a float: 2.0, 1.0, 1.0.

1.8Going deeper

  • Naming style (extra). Python programmers usually write multi-word names in snake_case such as student_name.
  • The same operator works on strings (extra). s += "x" means s = s + "x".
  • Swapping (extra). The tuple form makes a swap one line: x, y = y, x.
Python
s = "Py"
s += "thon"
print(s)
x, y = 1, 2
x, y = y, x
print(x, y)
Output
Python
2 1

1.9Exam tips and common mistakes

Exam tips
  • For "is this a valid name?" check the four rules in order: first character, allowed characters, keyword, then case only matters when comparing two names.
  • Trace short-hand operators line by line and write the type (int or float) next to each value.
Common mistakes
  • Writing first-name or 2nd_place as a name.
  • Using a variable after del.
  • Forgetting that /= turns an int into a float.
  • Unpacking three values into two names.

Practice questions (graded-assignment style)

Q1A valid name

Multiple Choice Question (MCQ): choose the one correct option.

Which of these is a valid variable name?

1
2nd_place
2
first-name
3
_total
4
for
Solution
Idea

Check the first character, the allowed characters and the keyword list.

  • _total starts with an underscore and has only allowed characters.
  • 2nd_place starts with a digit, first-name has a hyphen, and for is a keyword.
  • Answer: option 3.
Q2Short-hand chain

Numerical Answer Type (NAT).

What does this program print?

Python
x = 10
x += 3
x -= 2
x *= 2
x /= 2
x %= 3
x //= 2
x **= 3
print(x)
Solution
Idea

Trace x line by line; after /= it is a float.

Python
x = 10
x += 3
x -= 2
x *= 2
x /= 2
x %= 3
x //= 2
x **= 3
print(x)
Output
1.0
  • 10 → 13 → 11 → 22 → 11.0 → 2.0 → 1.0 → 1.0.
  • Answer: 1.0
Q3Delete and print

Multiple Choice Question (MCQ): choose the one correct option.

What does the program do?

Python
x = y = z = 8
print(x, z)
del y
print(y)
1
Prints 8 8 only
2
Prints 8 8, then raises a NameError for y
3
Prints None
4
Raises a SyntaxError before running
Solution
Idea

del y removes only the name y.

Python
x = y = z = 8
print(x, z)
del y
print(y)
Error
8 8
NameError: name 'y' is not defined
  • x = y = z = 8 gives all three names the value 8; print(x, z) prints 8 8.
  • After del y, print(y) raises NameError.
  • Answer: option 2.
Q4Unpacking

Multiple Choice Question (MCQ): choose the one correct option.

What happens when this runs?

Python
a, b = 1, 2, 3
1
It prints 1 2
2
It prints 1 2 3
3
It raises a ValueError
4
It raises a NameError
Solution
Idea

Count the names and the values.

Python
a, b = 1, 2, 3
Error
ValueError: too many values to unpack (expected 2, got 3)
  • Two names but three values: the numbers do not match, so Python raises ValueError.
  • Answer: option 3.
Q5Dynamic typing facts

Multiple Select Question (MSQ): select all that apply.

Choose the correct statements.

1
A variable can refer to an int and later to a string.
2
The type must be declared before the first assignment.
3
The type belongs to the value, not the name.
4
Age and age are the same variable.
Solution
Idea

Recall dynamic typing and case-sensitivity.

  • Statements 1 and 3 are true.
  • Statement 2 is false (no declaration), and statement 4 is false (names are case-sensitive).
  • Answer: options 1 and 3.
Q6Swap

Numerical Answer Type (NAT).

What is printed? (Give the two numbers separated by a space.)

Python
x, y = 1, 2
x, y = y, x
print(x, y)
Solution
Idea

The right side is evaluated first.

Python
x, y = 1, 2
x, y = y, x
print(x, y)
Output
2 1
  • x, y = y, x builds (2, 1) first and then assigns, so the values swap.
  • Answer: 2 1
Revision overview
NamesMeaningful, readable
snake_case (extra)
RulesLetter or _ first
No -, no keywords
Case-sensitive
TypingDynamic: the value has
the type
VariablesWeek 2 · Part 1
Assignmentx, y = 1, 2
x = y = z = 8
unpacking: counts match
Removaldel x
then x is a NameError
Short-hand+= -= *= /= %= //= **=
/= gives a float
Revision: how to name, assign and update variables
Next · BasicsOperators and Strings: Membership, Chaining, Escapes, Quotes
02
Basics

Operators and Strings: Membership, Chaining, Escapes, Quotes

Testing membership, chaining comparisons, and writing special characters and multi-line text in strings.

2.1Membership operators

OperatorMeaningExample
invalue is presentx in y
not invalue is not presentx not in y
Python
sentence = "I am Ayush"
print("Ayush" in sentence)
print("boy" not in sentence)
Output
True
True

A membership test always gives True or False. For strings it checks for a substring, not just a whole word.

Python
sentence = "I am Ayush"
print("Ay" in sentence)
print("ayush" in sentence)
print(" " in sentence)
print(3 in [1, 2, 3])
Output
True
False
True
True
Extra. Case matters: "ayush" in sentence is False. For a list, in needs a whole element.

2.2Chaining comparison operators

Chained comparison

x < y < z is equivalent to x < y and y < z. The middle expression is evaluated only once. Similarly a < b > c means (a < b) and (b > c).

0123456789101112x = 51101 < x < 10 ≡ 1 < x and x < 10Truex is read once; the middle expression is evaluated only once
Figure 3. 1 < x < 10 holds for x = 5
Python
x = 5
print(1 < x < 10)
print(10 < x < 20)
print(x < 10 < x * 10 < 100)
Output
True
False
True
  1. 1 < 5 < 10: both 1 < 5 and 5 < 10 are true, so True.
  2. 10 < 5 < 20: the first test 10 < 5 is false, so False.
  3. 5 < 10 < 50 < 100: three tests, all true, so True.
Python
a, b, c = 1, 5, 3
print(a < b > c)
print((a < b) and (b > c))
Output
True
True

2.3Escape characters

EscapeResult
\'single quote
\"double quote
\nnew line
\ttab
Python
print("It's Python")
print("He said \"Hello\"")
print("First line\nSecond line")
print("Name:\tEngiKode")
Output
It's Python
He said "Hello"
First line
Second line
Name:	EngiKode
Python
text = 'We are the so called \'Viking\' from north.'
print(text)
Output
We are the so called 'Viking' from north.
Remember. An escape such as \n is written with two characters but is stored as one: len("a\tb") is 3.

2.4Different types of quotes

  • Single quotes '...' and double quotes "..." make ordinary strings; they behave the same.
  • Triple quotes ('''...''' or """...""") can span multiple lines.
Python
single = 'Python'
double = "Python"
triple_single = '''Python
Week 2'''
triple_double = """EngiKode
Python"""
print(single)
print(double)
print(triple_single)
print(triple_double)
Output
Python
Python
Python
Week 2
EngiKode
Python
Pick the quote that avoids escapes

"It's Python" needs no backslash because the outer quotes are double. Use whichever quote type does not appear inside the text.

2.5Exam tips and common mistakes

Exam tips
  • Expand a chain into and parts and test them left to right; stop at the first false part.
  • Read the escape sequences first, then count what is printed on each line.
Common mistakes
  • Treating \n as two printed characters.
  • Thinking a < b < c compares a with c only.
  • Forgetting that in is case-sensitive.

Practice questions (graded-assignment style)

Q1Chained output

Multiple Choice Question (MCQ): choose the one correct option.

What does the program print?

Python
x = 5
print(1 < x < 10)
print(10 < x < 20)
print(x < 10 < x * 10 < 100)
1
True False True on three lines
2
True True True on three lines
3
False False True on three lines
4
It raises an error
Solution
Idea

Expand each chain into and parts.

Python
x = 5
print(1 < x < 10)
print(10 < x < 20)
print(x < 10 < x * 10 < 100)
Output
True
False
True
  • 1 < 5 < 10: True. 10 < 5 < 20: False. 5 < 10 < 50 < 100: True.
  • Answer: option 1.
Q2Membership

Multiple Select Question (MSQ): select all that apply.

With s = "I am Ayush", which expressions are True?

Python
s = "I am Ayush"
print("Ayush" in s)
print("boy" not in s)
print("ayush" in s)
print("Ay" in s)
1
"Ayush" in s
2
"boy" not in s
3
"ayush" in s
4
"Ay" in s
Solution
Idea

Strings are searched for substrings, with case.

Python
s = "I am Ayush"
print("Ayush" in s)
print("boy" not in s)
print("ayush" in s)
print("Ay" in s)
Output
True
True
False
True
  • Options 1, 2 and 4 are True. Option 3 is False because of the lower-case a.
  • Answer: options 1, 2 and 4.
Q3Escapes

Multiple Choice Question (MCQ): choose the one correct option.

How many lines does this print, and what does the second one show?

Python
print("First\n\tEngiKode")
1
2 lines; second is Second line shown with a tab
2
2 lines; the second starts with a tab then EngiKode
3
1 line only
4
2 lines; the second is \tEngiKode as text
Solution
Idea

\n breaks the line, \t inserts a tab.

Python
print("First\n\tEngiKode")
Output
First
	EngiKode
  • \n ends the first line, so there are two lines.
  • \t is a tab character, so the second line starts with a tab space before EngiKode.
  • Answer: option 2.
Q4Length of an escaped string

Numerical Answer Type (NAT).

What does the program print?

Python
print(len("a\tb\n"))
Solution
Idea

Each escape is a single character.

Python
print(len("a\tb\n"))
Output
4
  • "a\tb\n" has the characters a, tab, b, newline: 4.
  • Answer: 4
Q5a < b > c

Multiple Choice Question (MCQ): choose the one correct option.

With a = 1, b = 5, c = 9, what is a < b > c?

Python
a, b, c = 1, 5, 9
print(a < b > c)
1
True
2
False
3
5
4
An error
Solution
Idea

It means (a < b) and (b > c).

Python
a, b, c = 1, 5, 9
print(a < b > c)
Output
False
  • 1 < 5 is True but 5 > 9 is False, so the whole chain is False.
  • Answer: option 2.
Revision overview
Membershipin / not in
True or False
substring for strings
Chainingx < y < z means
x < y and y < z
Escapes\' \" \n \t
one character each
Operators and stringsWeek 2 · Part 2
QuotesSingle, double, triple
triple spans lines
Pitfallin is case-sensitive
TipChoose quotes to avoid escapes
Revision: testing membership, chaining comparisons and writing special characters
Next · StringsString Methods and the Caesar Cipher
03
Strings

String Methods and the Caesar Cipher

The Week 2 string methods, and a cipher that shifts letters with % 26.

Week 2 has a large set of string methods. For each one know what it does and whether it transforms the string (returns a new string) or checks a condition (returns True/False).

3.1Case methods: lower, upper, capitalize, title, swapcase

MethodWhat it doesResult for the sample
lower()all characters lowercasepython
upper()all characters uppercasePYTHON
capitalize()first character uppercaseI love python
title()first character of each word uppercaseI Love Python
swapcase()lower ↔ upperpYthON
Python
x = "PyTHon"
print(x.lower())
print(x.upper())
print(x.swapcase())
y = "i love python"
print(y.capitalize())
print(y.title())
Output
python
PYTHON
pYthON
I love python
I Love Python

3.2Check methods: islower, isupper, istitle, isdigit, isalpha, isalnum

These return True or False.

MethodTrue whenExample
islower()all (cased) characters are lowercase"python".islower() → True, "Python".islower() → False
isupper()all (cased) characters are uppercase"PYTHON".isupper() → True, "Python".isupper() → False
istitle()title-case rules hold"Python String Methods".istitle() → True
isdigit()all characters are digits"123".isdigit() → True, "123abc".isdigit() → False
isalpha()all characters are letters"abc".isalpha() → True, "abc123".isalpha() → False
isalnum()all characters are letters or digits"abc123".isalnum() → True, "abc123#".isalnum() → False
Python
print("python".islower())
print("Python".islower())
print("PYTHON".isupper())
print("Python".isupper())
print("Python String Methods".istitle())
print("Python string methods".istitle())
print("123".isdigit())
print("123abc".isdigit())
print("abc".isalpha())
print("abc123".isalpha())
print("abc123".isalnum())
print("abc123#".isalnum())
Output
True
False
True
False
True
False
True
False
True
False
True
False
Extra. "".isdigit() (an empty string) is False, and a space or # is neither a letter nor a digit, which is why "abc123#".isalnum() is False.

3.3Trimming: strip, lstrip, rstrip

MethodPurpose
strip()removes specified characters from both ends
lstrip()removes them from the left
rstrip()removes them from the right
Python
x = "---Python---"
print(x.strip("-"))
print(x.lstrip("-"))
print(x.rstrip("-"))
Output
Python
Python---
---Python
the green characters survivex.strip("-")---Python---→"Python"x.lstrip("-")---Python---→"Python---"x.rstrip("-")---Python---→"---Python"
Figure 4. Only the ends are trimmed, and only the given characters
Extra. With no argument, strip() removes whitespace. Characters in the middle are never removed.
Python
print("  hi  ".strip() + "|")
print("--a-b--".strip("-"))
Output
hi|
a-b

3.4Searching and replacing

MethodReturns
startswith(v)True if the string starts with v
endswith(v)True if it ends with v
count(v)how many times v occurs
index(v)position of v; ValueError if absent
replace(old, new)a string with old replaced by new
Python
x = "Python"
print(x.startswith("P"))
print(x.startswith("p"))
print(x.endswith("n"))
print(x.endswith("N"))
Output
True
False
True
False
Python
x = "python string methods"
print(x.count("t"))
print(x.count("s"))
print("python".index("t"))
Output
3
2
2
Python
x = "python string methods"
x = x.replace("python", "Python")
x = x.replace("methods", "Methods")
print(x)
Output
Python string Methods
Python
print("python".index("z"))
Error
ValueError: substring not found
Important. index() raises ValueError when the value is not found. (Extra: find() returns -1 instead.)

3.5Methods return new strings

Strings cannot be changed in place. A method such as upper() or replace() returns a new string and leaves the original untouched. That is why the replace example assigns back: x = x.replace(...).

Python
x = "python"
x.upper()
print(x)
x = x.upper()
print(x)
Output
python
PYTHON

3.6Quick table

MethodMain use
lower() upper()lowercase / uppercase
capitalize() title()first character / each word
swapcase()swap letter case
islower() isupper() istitle()case checks
isdigit() isalpha() isalnum()content checks
strip() lstrip() rstrip()trim both / left / right
startswith() endswith()start / end checks
count() index() replace()count, find position, replace

3.7The Caesar cipher

A Caesar cipher is a substitution technique: each character is replaced by the character a fixed number of places further along the alphabet. The fixed number is the shift. With a shift of 1: A → B, B → C, C → D, ...

The alphabet has 26 letters, so % 26 wraps an index that goes beyond 25 back to the start:

Python
alpha = "abcdefghijklmnopqrstuvwxyz"
i = 25
print(alpha[i % 26])
j = 28
print(alpha[j % 26])
k = 26
print(alpha[k % 26])
Output
z
c
a
alpha = "abcdefghijklmnopqrstuvwxyz"a0b1c2d3e4f5g6h7i8j9k10l11m12n13o14p15q16r17s18t19u20v21w22x23y24z25+1s → index 1818 + 1 = 1919 % 26 = 19alpha[19] = tz → index 2525 + 1 = 2626 % 26 = 0alpha[0] = a% 26 brings an index that goes past 25 back to the start
Figure 5. s → t is a plain shift; z → a needs the % 26 wrap
Core formula

alpha[(alpha.index(character) + shift) % 26]

Find the letter's position, add the shift, wrap with % 26, and read the letter at the new position.

Python
alpha = "abcdefghijklmnopqrstuvwxyz"
name = "sky"
copy = ""
k = 1
copy = copy + alpha[(alpha.index(name[0]) + k) % 26]
copy = copy + alpha[(alpha.index(name[1]) + k) % 26]
copy = copy + alpha[(alpha.index(name[2]) + k) % 26]
print(copy)
Output
tlz
LetterIndex+ shift 1% 26New letter
s181919t
k101111l
y242525z

3.8Going deeper

  • Wrap-around with y (extra). With shift 3, y (index 24) goes to 27 % 26 = 1, which is b.
  • Decoding (extra). Subtract the shift instead: (index - k) % 26. Python's % never gives a negative result here, so (0 - 1) % 26 is 25.
  • Typing less (extra). The three repeated lines can be written as a loop over the letters (loops come later in the course).
Python
alpha = "abcdefghijklmnopqrstuvwxyz"
name = "sky"
copy = ""
k = 3
for ch in name:
    copy = copy + alpha[(alpha.index(ch) + k) % 26]
print(copy)
print((0 - 1) % 26)
Output
vnb
25

3.9find, split and join: the string tools that programs use most

Section 3.4 introduced index(), count() and replace(). Three more tools finish the toolkit: find() (a safer index()), split() and join(). The last two are how a program turns one line of typed input into several values, and back.

A. find, rfind, index and count in detail

  • s.find(v) returns the position of the first match, or -1 if there is none. s.index(v) does the same but raises ValueError when there is none. s.rfind(v) searches from the right and gives the position of the last match.
  • All of them accept optional start and end positions: s.find(v, 3) starts looking at index 3.
  • s.count(v) counts non-overlapping matches, scanning left to right.
  • s.replace(old, new, k) replaces only the first k matches when you give k.
  • v in s answers only "is it there?" (True/False); find also says where.
Python
s = "banana bandana"
print(s.find("ana"))        # first match
print(s.find("ana", 3))     # start looking at index 3
print(s.rfind("ana"))       # last match
print(s.find("xyz"))        # not found: -1, no error
print(s.count("ana"))       # non-overlapping matches
print("aaaa".count("aa"))   # 2, not 3: matches do not overlap
print(s.replace("ana", "ANA", 1))   # only the first match
Output
1
3
11
-1
2
2
bANAna bandana
Python
print("banana".index("xyz"))
Output
ValueError: substring not found
find versus index. Use find when "not present" is a normal outcome you will test for (if s.find(v) == -1). Use index when absence would be a bug. A classic slip: if s.find("a"): is wrong, because -1 is truthy and a match at position 0 is falsy. Write if s.find("a") != -1: or if "a" in s:.

B. split and join

  • s.split() with no argument splits on any run of whitespace and drops empty pieces. s.split(sep) splits at every sep and keeps empty pieces. s.split(sep, 1) splits at most once. The result is always a list of strings.
  • sep.join(list_of_strings) glues the pieces together with sep between them. The separator is the string you call join on; the list is the argument.
  • Reading numbers: input() returns one string, so a, b = input().split() splits a line like "3 4" into two strings, and each still needs int().
Python
print("a,b,,c".split(","))        # empty piece is kept
print("  a   b ".split())          # whitespace: no empty pieces
print("a-b-c".split("-", 1))       # at most one split
print("-".join(["x", "y", "z"]))
print("".join(reversed("abc")))    # reverse a string
line = "3 4"                       # what input() would return
a, b = line.split()
print(a, b, "sum", int(a) + int(b))
Output
['a', 'b', '', 'c']
['a', 'b']
['a', 'b-c']
x-y-z
cba
3 4 sum 7
Types after split. "3 4".split() gives ["3", "4"], two strings. Adding them directly gives "34", not 7. Convert each piece with int() first.

C. A few more checks and a palindrome test

  • startswith and endswith accept a tuple of alternatives: name.endswith((".csv", ".txt")).
  • isalnum() is True when every character is a letter or digit (and the string is non-empty); isspace() when every character is whitespace; isdigit() only for the digits 0 to 9, so "-12" and "3.5" are False.
  • A word is a palindrome when it equals its reverse: s == s[::-1]. For a test that ignores case, lower both sides first.
Python
print("file.csv".endswith((".csv", ".txt")))
print("abc 123".isalnum())
print("  ".isspace())
print("-12".isdigit())
print("3.5".isdigit())
print("level" == "level"[::-1])
print("Level".lower() == "Level".lower()[::-1])
Output
True
False
True
False
False
True
True

3.10Exam tips and common mistakes

Exam tips
  • Label each method as a transform or a check before predicting output.
  • For the cipher, write the index of every letter first, then add the shift, then % 26.
Common mistakes
  • Expecting x.upper() to change x without assigning the result.
  • Using index() for a value that may be absent: it raises ValueError.
  • Forgetting % 26, which fails for letters near the end such as z.
  • Confusing strip("-") (removes dashes at the ends) with replace("-", "") (removes all dashes).

Practice questions (graded-assignment style)

Q1Title and swapcase

Multiple Choice Question (MCQ): choose the one correct option.

What does this print?

Python
print("i love python".title())
print("PyTHon".swapcase())
1
I Love Python then pYthON
2
I love python then pYthON
3
I Love Python then PYTHON
4
i love python then pythOn
Solution
Idea

title() capitalises every word; swapcase() flips every letter.

Python
print("i love python".title())
print("PyTHon".swapcase())
Output
I Love Python
pYthON
  • "i love python".title() is I Love Python.
  • "PyTHon".swapcase() is pYthON.
  • Answer: option 1.
Q2Counting

Numerical Answer Type (NAT).

What does the program print?

Python
x = "python string methods"
print(x.count("t") + x.count("s"))
Solution
Idea

Add the two counts.

Python
x = "python string methods"
print(x.count("t") + x.count("s"))
Output
5
  • "t" occurs 3 times (python, string, methods) and "s" occurs 2 times (string, methods): 3 + 2 = 5.
  • Answer: 5
Q3Trim

Multiple Choice Question (MCQ): choose the one correct option.

What does the program print?

Python
x = "---Python---"
print(x.rstrip("-"))
1
Python---
2
---Python
3
Python
4
---Python---
Solution
Idea

rstrip trims the right end only.

Python
x = "---Python---"
print(x.rstrip("-"))
Output
---Python
  • rstrip("-") removes the three dashes at the right, leaving ---Python.
  • Answer: option 2.
Q4Index of a missing letter

Multiple Choice Question (MCQ): choose the one correct option.

What happens?

Python
print("python".index("z"))
1
It prints -1
2
It prints None
3
It raises a ValueError
4
It prints 0
Solution
Idea

index() raises an error when the value is absent.

Python
print("python".index("z"))
Error
ValueError: substring not found
  • "python" has no z, so index("z") raises ValueError.
  • Answer: option 3.
Q5Caesar shift

Numerical Answer Type (NAT).

What does this print?

Python
alpha = "abcdefghijklmnopqrstuvwxyz"
print(alpha[(alpha.index("s") + 3) % 26] + alpha[(alpha.index("k") + 3) % 26] + alpha[(alpha.index("y") + 3) % 26])
Solution
Idea

Add 3 to each index and wrap with % 26.

Python
alpha = "abcdefghijklmnopqrstuvwxyz"
print(alpha[(alpha.index("s") + 3) % 26] + alpha[(alpha.index("k") + 3) % 26] + alpha[(alpha.index("y") + 3) % 26])
Output
vnb
  • s(18)+3 = 21 → v; k(10)+3 = 13 → n; y(24)+3 = 27 → 27 % 26 = 1 → b.
  • Answer: vnb
Q6Transform or check?

Multiple Select Question (MSQ): select all that apply.

Which of these return True/False (checks)?

1
isdigit()
2
upper()
3
startswith()
4
replace()
Solution
Idea

A check answers a yes/no question.

  • isdigit() and startswith() return booleans.
  • upper() and replace() return new strings.
  • Answer: options 1 and 3.
Q7Wrap-around index

Numerical Answer Type (NAT).

What does this print?

Python
alpha = "abcdefghijklmnopqrstuvwxyz"
j = 28
print(alpha[j % 26])
Solution
Idea

Compute 28 % 26 first.

Python
alpha = "abcdefghijklmnopqrstuvwxyz"
j = 28
print(alpha[j % 26])
Output
c
  • 28 % 26 = 2, and alpha[2] is c.
  • Answer: c
Q1find versus index

Multiple Select Question (MSQ): select all that apply.

Consider s = "Mississippi". Select all the true statements.

1
s.find("ss") is 2
2
s.find("ss", 3) is 5
3
s.count("ss") is 2
4
s.find("z") raises a ValueError
5
s.rfind("ss") is 5
Solution
Idea

Index the letters: M0 i1 s2 s3 i4 s5 s6 i7 p8 p9 i10. Run each call.

Python
s = "Mississippi"
print(s.find("ss"))
print(s.find("ss", 3))
print(s.count("ss"))
print(s.find("z"))
print(s.rfind("ss"))
Output
2
5
2
-1
5
  • 1 ✓ first ss starts at index 2. 2 ✓ searching from 3 skips the first and finds index 5. 3 ✓ two non-overlapping matches.
  • 4 ✗ find returns -1; it is index that raises ValueError. 5 ✓ the last match starts at index 5.
  • Answer: options 1, 2, 3 and 5.
Q2Overlapping matches

Numerical Answer Type (NAT).

What does the program print?

Python
print("aaaaa".count("aa"))
Solution
Idea

count scans left to right and never reuses characters.

Python
print("aaaaa".count("aa"))
Output
2
  • Match at positions 0 to 1, then the scan resumes at 2 and matches 2 to 3; the final a is left over. Two matches.
  • Counting overlapping matches (positions 0, 1, 2, 3) would give 4. That is not what count does.
  • Answer: 2
Q3Reading what split returns

Multiple Choice Question (MCQ): choose the one correct option.

What does the program print?

Python
line = "10 20 30"
parts = line.split()
print(parts[0] + parts[1])
1
30
2
1020
3
10 20
4
an error
Solution
Idea

split() returns a list of strings; + on strings joins them.

Python
line = "10 20 30"
parts = line.split()
print(parts[0] + parts[1])
Output
1020
  • parts is ['10', '20', '30']. "10" + "20" is "1020". To add the numbers write int(parts[0]) + int(parts[1]), which is 30.
  • Answer: option 2.
Q4Replace only the first match

Multiple Choice Question (MCQ): choose the one correct option.

What is printed by the program?

Python
s = "banana"
print(s.replace("a", "o", 2))
1
bonono
2
bonona
3
bononb
4
bonana
Solution
Idea

The third argument is the maximum number of replacements, counted from the left.

Python
s = "banana"
print(s.replace("a", "o", 2))
Output
bonona
  • The first two as (positions 1 and 3) become o; the last stays. Result bonona.
  • Answer: option 2.
Q5Joining and reversing

Multiple Select Question (MSQ): select all that apply.

Which of the following print yhp?

1
print("php"[::-1])
2
print("".join(reversed("phy")))
3
print("phy"[::-1])
4
print("-".join("phy")[::-1])
Solution
Idea

Reversing "phy" gives "yhp". Check each option.

Python
print("php"[::-1])
print("".join(reversed("phy")))
print("phy"[::-1])
print("-".join("phy")[::-1])
Output
php
yhp
yhp
y-h-p
  • 1 ✗ reverses php (a palindrome), giving php. 2 ✓. 3 ✓.
  • 4 ✗ "-".join("phy") is p-h-y, and its reverse is y-h-p with the hyphens.
  • Answer: options 2 and 3.
Revision overview
Caselower upper capitalize
title swapcase
Checksislower isupper istitle
isdigit isalpha isalnum
→ True / False
Trimstrip lstrip rstrip
String methodsWeek 2 · Part 3
Searchstartswith endswith
count index replace
RememberMethods return new strings
index raises ValueError
Caesaralpha[(alpha.index(c) + k) % 26]
Revision: what each string method does and how the cipher wraps
Next · DecisionsConditional Statements
04
Decisions

Conditional Statements

if, else, elif, logical operators, nested if and the conditional expression.

Decision-making lets a program run different statements depending on a condition. This part covers if, if...else, if...elif...else, logical operators in conditions, nested if and the conditional (ternary) expression.

4.1The if statement

Syntax

if expression: followed by an indented block of statement(s).

The block runs only when the expression is True. Statements of the block must be indented consistently.

Python
x = 10
y = 5
if x > y:
    text = "Hello World"
print(text)
Output
Hello World
Python
x = 3
y = 5
if x > y:
    text = "Hello World"
print(text)
Error
NameError: name 'text' is not defined

The second program shows what happens when the condition is false: the block is skipped, text is never created, and print(text) raises a NameError. (Extra.)

4.2if ... else

Python
age = 15
if age >= 18:
    print("User is old enough")
else:
    print("User is not old enough")
Output
User is not old enough

else has no condition; it runs when the if condition is false.

4.3if ... elif ... else

if x > 10 :TrueFalserun the if blockelif x < 10 :TrueFalserun the elif blockelse blockonly the first true branch runs; the rest are skipped
Figure 6. Conditions are tested top to bottom; the first true block runs
Python
x = 5
if x > 10:
    print("Yes")
elif x < 10:
    print("No")
else:
    print("x is 10")
Output
No
Python
x = 10
if x > 10:
    print("x is more than 10")
elif x < 10:
    print("x is less than 10")
else:
    print("x is 10 because it is neither more nor less")
Output
x is 10 because it is neither more nor less
First true wins

Once a branch runs, the remaining elif and else parts are skipped, even if they would also be true. So the order of branches matters.

Python
x = 95
if x > 50:
    print("above 50")
elif x > 90:
    print("above 90")
Output
above 50

4.4Logical operators in conditions

Use and (both must be true) and or (at least one must be true) to combine tests.

Python
x = 10
y = 5
if (x == 10) and (y == 5):
    text = "Hello World"
print(text)
if (x == 10) or (y == 10):
    print("At least one condition is true")
Output
Hello World
At least one condition is true
Expressionx = 10, y = 5
(x == 10) and (y == 5)True
(x == 10) and (y == 10)False
(x == 10) or (y == 10)True
(x == 0) or (y == 0)False

4.5Nested if

An if can sit inside another if (or else). The inner test runs only if the outer one let the program in.

Python
x = 15
if x > 5:
    print("x is more than 5")
    if x > 10:
        print("x is more than 10")
    else:
        print("x is between 5 and 10")
else:
    print("x is 5 or below")
Output
x is more than 5
x is more than 10
xOutput
15more than 10
8between 5 and 10
35 or below

4.6Conditional (ternary) expression

Form

value_if_true if condition else value_if_false

A one-line choice between two values, handy for simple assignments.

text = "x is 10" if x == 10 else "x is not 10"value_if_trueused when condition is trueconditiontested firstvalue_if_falseused otherwiseone line, one value
Figure 7. The three parts of a conditional expression
Python
x = 10
text = "x is 10" if x == 10 else "x is not 10"
print(text)
Output
x is 10
Python
x = 7
print("even" if x % 2 == 0 else "odd")
Output
odd

4.7Going deeper

  • Indentation is the syntax. A body that is not indented is an IndentationError (extra).
  • Use == to compare. A single = assigns and is a syntax error inside an if (extra).
  • elif versus separate ifs (extra). Separate if statements are all tested; an elif chain stops at the first true branch.
Python
x = 95
if x > 50:
    print("above 50")
if x > 90:
    print("above 90")
Output
above 50
above 90
Python
x = 5
if x > 3:
print("big")
Error
IndentationError: expected an indented block after 'if' statement on line 2

4.8Exam tips and common mistakes

Exam tips
  • Trace from the top: test the first condition, run its block if true and skip everything else in the chain.
  • For nested ifs, indent level tells you which else belongs to which if.
Common mistakes
  • Writing = instead of == in a condition.
  • Forgetting the colon after if, elif or else.
  • Putting a broader test before a narrower one in an elif chain.
  • Mixing indentation levels.

Practice questions (graded-assignment style)

Q1elif chain

Multiple Choice Question (MCQ): choose the one correct option.

What does the program print?

Python
x = 5
if x > 10:
    print("Yes")
elif x < 10:
    print("No")
else:
    print("x is 10")
1
Yes
2
No
3
x is 10
4
Nothing
Solution
Idea

Test the conditions top to bottom.

Python
x = 5
if x > 10:
    print("Yes")
elif x < 10:
    print("No")
else:
    print("x is 10")
Output
No
  • 5 > 10 is false, 5 < 10 is true, so No is printed and the rest is skipped.
  • Answer: option 2.
Q2Order of branches

Multiple Choice Question (MCQ): choose the one correct option.

What is printed?

Python
x = 95
if x > 50:
    print("above 50")
elif x > 90:
    print("above 90")
1
above 90
2
above 50
3
Both lines
4
Nothing
Solution
Idea

The first true branch wins.

Python
x = 95
if x > 50:
    print("above 50")
elif x > 90:
    print("above 90")
Output
above 50
  • 95 > 50 is true, so the first block runs and the elif is never tested.
  • Answer: option 2.
Q3Nested if

Multiple Choice Question (MCQ): choose the one correct option.

What is printed for x = 8?

Python
x = 8
if x > 5:
    if x > 10:
        print("x is more than 10")
    else:
        print("x is between 5 and 10")
else:
    print("x is 5 or below")
1
x is more than 10
2
x is between 5 and 10
3
x is 5 or below
4
Nothing
Solution
Idea

The outer test passes; then decide the inner one.

Python
x = 8
if x > 5:
    if x > 10:
        print("x is more than 10")
    else:
        print("x is between 5 and 10")
else:
    print("x is 5 or below")
Output
x is between 5 and 10
  • 8 > 5 is true, so the outer block runs; 8 > 10 is false, so the inner else prints.
  • Answer: option 2.
Q4Ternary

Numerical Answer Type (NAT).

What does the program print?

Python
x = 11
text = "x is 10" if x == 10 else "x is not 10"
print(text)
Solution
Idea

The condition decides which value is chosen.

Python
x = 11
text = "x is 10" if x == 10 else "x is not 10"
print(text)
Output
x is not 10
  • x == 10 is false for x = 11, so the value after else is used.
  • Answer: x is not 10
Q5Logical operators

Multiple Select Question (MSQ): select all that apply.

For x = 10, y = 5, which conditions are true?

Python
x = 10
y = 5
print((x == 10) and (y == 5))
print((x == 10) and (y == 10))
print((x == 10) or (y == 10))
print((x == 0) or (y == 0))
1
(x == 10) and (y == 5)
2
(x == 10) and (y == 10)
3
(x == 10) or (y == 10)
4
(x == 0) or (y == 0)
Solution
Idea

and needs both; or needs one.

Python
x = 10
y = 5
print((x == 10) and (y == 5))
print((x == 10) and (y == 10))
print((x == 10) or (y == 10))
print((x == 0) or (y == 0))
Output
True
False
True
False
  • Options 1 and 3 are true.
  • Option 2 fails on y == 10; option 4 fails on both parts.
  • Answer: options 1 and 3.
Q6Separate ifs

Multiple Choice Question (MCQ): choose the one correct option.

What does this print?

Python
x = 95
if x > 50:
    print("above 50")
if x > 90:
    print("above 90")
1
Only above 50
2
Only above 90
3
above 50 then above 90
4
Nothing
Solution
Idea

Two separate if statements are both tested.

Python
x = 95
if x > 50:
    print("above 50")
if x > 90:
    print("above 90")
Output
above 50
above 90
  • There is no elif, so each if is tested on its own and both are true.
  • Answer: option 3.
Revision overview
ifBlock runs when the
expression is True
else / elifelse: otherwise
elif: more conditions
first true wins
Combineand: both
or: at least one
Conditional statementsWeek 2 · Part 4
Nestedif inside if
indent shows ownership
Ternarya if condition else b
Watch== not =
colon
branch order
Revision: making the program choose between blocks
Next · DecisionsPractice Zone
05
Decisions

Practice Zone

Four programs that turn decision rules into code, traced with real inputs.

Try each problem yourself before reading the solution. Every program below was run for real; the sample runs show what it prints.

5.1Problem 1: even or odd

Take an integer as input and decide whether it is even or odd. A number is even when dividing by 2 leaves remainder 0.

Python
x = int(input("Enter a number: "))
if x % 2 == 0:
    print("Even")
else:
    print("Odd")
Output
Enter a number: 7
Odd
InputOutput
7Odd
10Even
0Even
-3Odd
Extra. -3 % 2 is 1 in Python, so negative odd numbers are still reported as Odd.

5.2Problem 2: the last digit

Decide whether the last digit of a number is 0, 5 or something else. A last digit of 0 or 5 means the number is divisible by 5; among those, divisible by 10 means the last digit is 0. That is a nested if.

Python
x = int(input("Enter a number: "))
if x % 5 == 0:
    if x % 10 == 0:
        print("0")
    else:
        print("5")
else:
    print("Other")
Output
Enter a number: 25
5
Input% 5 == 0 ?% 10 == 0 ?Output
40yesyes0
25yesno5
7no—Other

5.3Problem 3: student grade

GradeMarks (as given)
A>90> 90 and ≤100\leq 100
B>80> 80
C≥70\geq 70
D≥60\geq 60
E≤60\leq 60 and >0> 0
Python
x = int(input("Enter your marks: "))

if x > 90 and x <= 100:
    print("A")
elif x > 80:
    print("B")
elif x >= 70:
    print("C")
elif x >= 60:
    print("D")
elif x <= 60 and x > 0:
    print("E")
else:
    print("Not Valid")
Output
Enter your marks: 72
C
E1–59D60–69C70–80B81–90A91–100060708090100Not Validx > 100prints B (bug)Problem 3: which mark gets which grade (as the code behaves)elif order decides: 60 is caught by D before E; marks above 100 fall into B
Figure 8. How the elif chain actually grades each mark
MarksOutputWhy
95Afirst test: 95 > 90 and ≤ 100
85Bnot A; 85 > 80
80C80 > 80 is false, so it falls to ≥ 70
72C≥ 70
60D≥ 60 is tested before the E branch
30Eonly the last branch fits
0Not Validfails every test
Order does the work
  • Each elif only runs if every test above it was false, so x > 80 really means "above 80 and not A".
  • The table says E is "≤ 60", but 60 is also "≥ 60" (D). The code resolves the overlap in favour of D, because D comes first.
Correction (extra). The source program has a gap: marks above 100 are not rejected, they print B (the output for 105 above). A safer version checks the valid range first.
Python
x = int(input("Enter your marks: "))

if x <= 0 or x > 100:
    print("Not Valid")
elif x > 90:
    print("A")
elif x > 80:
    print("B")
elif x >= 70:
    print("C")
elif x >= 60:
    print("D")
else:
    print("E")
Output
Enter your marks: 105
Not Valid
MarksOutput (safer version)
105Not Valid
100A
91A
60D
59E
0Not Valid

5.4Problem 4: travel decision

A flowchart problem: travel from City A to City B. First ask whether the trip time is longer or shorter than a threshold, then compare the price with a threshold to pick coach/train (long trip) or red-eye/daytime flight (short trip).

time >= longer ?yesnoprice >= higher ?price >= higher ?TrainCoachDaytime FlightRed Eye Flightprint("Arrive City B")both branches end at the same final print
Figure 9. The decision tree behind the program
Python
print("Travel from City A to City B")

time = int(input("Enter time: "))
longer = int(input("Define longer: "))

if time >= longer:
    price = int(input("Enter price: "))
    higher = int(input("Define higher: "))

    if price >= higher:
        print("Train")
    else:
        print("Coach")
else:
    price = int(input("Enter price: "))
    higher = int(input("Define higher: "))

    if price >= higher:
        print("Daytime Flight")
    else:
        print("Red Eye Flight")

print("Arrive City B")
Output
Travel from City A to City B
Enter time: 5
Define longer: 3
Enter price: 200
Define higher: 100
Train
Arrive City B
timelongerpricehigherResult
53200100Train
5350100Coach
13200100Daytime Flight
1350100Red Eye Flight

Notice that higher and longer are values you define, so the program is really two nested decisions. The last line, print("Arrive City B"), is outside both blocks and runs every time.

5.5Exam tips and common mistakes

Exam tips
  • Make a small table of inputs and trace each one through the branches.
  • Test boundary values (60, 70, 80, 90, 100) because that is where branch order matters.
Common mistakes
  • Using > where the boundary should be included (>=).
  • Forgetting int(...) around input, which leaves a string and breaks the comparison.
  • Assuming the code rejects invalid marks without checking the range.

Practice questions (graded-assignment style)

Q1Grade for 80

Multiple Choice Question (MCQ): choose the one correct option.

For the input 80, what does the grade program print?

Python
x = int(input("Enter your marks: "))

if x > 90 and x <= 100:
    print("A")
elif x > 80:
    print("B")
elif x >= 70:
    print("C")
elif x >= 60:
    print("D")
elif x <= 60 and x > 0:
    print("E")
else:
    print("Not Valid")
1
A
2
B
3
C
4
D
Solution
Idea

Is 80 > 80 true?

Python
x = int(input("Enter your marks: "))

if x > 90 and x <= 100:
    print("A")
elif x > 80:
    print("B")
elif x >= 70:
    print("C")
elif x >= 60:
    print("D")
elif x <= 60 and x > 0:
    print("E")
else:
    print("Not Valid")
Output
Enter your marks: 80
C
  • 80 > 90 is false, 80 > 80 is false, 80 >= 70 is true: C.
  • Answer: option 3.
Q2Grade for 60

Multiple Choice Question (MCQ): choose the one correct option.

For the input 60, what is printed?

Python
x = int(input("Enter your marks: "))

if x > 90 and x <= 100:
    print("A")
elif x > 80:
    print("B")
elif x >= 70:
    print("C")
elif x >= 60:
    print("D")
elif x <= 60 and x > 0:
    print("E")
else:
    print("Not Valid")
1
C
2
D
3
E
4
Not Valid
Solution
Idea

Which of >= 60 and <= 60 is tested first?

Python
x = int(input("Enter your marks: "))

if x > 90 and x <= 100:
    print("A")
elif x > 80:
    print("B")
elif x >= 70:
    print("C")
elif x >= 60:
    print("D")
elif x <= 60 and x > 0:
    print("E")
else:
    print("Not Valid")
Output
Enter your marks: 60
D
  • >= 60 comes before <= 60 and > 0, so D is printed.
  • Answer: option 2.
Q3A bug

Multiple Choice Question (MCQ): choose the one correct option.

For the input 105, what does the original grade program print?

Python
x = int(input("Enter your marks: "))

if x > 90 and x <= 100:
    print("A")
elif x > 80:
    print("B")
elif x >= 70:
    print("C")
elif x >= 60:
    print("D")
elif x <= 60 and x > 0:
    print("E")
else:
    print("Not Valid")
1
A
2
B
3
Not Valid
4
An error
Solution
Idea

Follow the chain: the first test needs x <= 100.

Python
x = int(input("Enter your marks: "))

if x > 90 and x <= 100:
    print("A")
elif x > 80:
    print("B")
elif x >= 70:
    print("C")
elif x >= 60:
    print("D")
elif x <= 60 and x > 0:
    print("E")
else:
    print("Not Valid")
Output
Enter your marks: 105
B
  • The first test fails (105 is above 100) but 105 > 80 is true, so B is printed.
  • Answer: option 2.
Q4Last digit

Numerical Answer Type (NAT).

What does the program print for the input 25?

Python
x = int(input("Enter a number: "))
if x % 5 == 0:
    if x % 10 == 0:
        print("0")
    else:
        print("5")
else:
    print("Other")
Solution
Idea

25 is divisible by 5 but not by 10.

Python
x = int(input("Enter a number: "))
if x % 5 == 0:
    if x % 10 == 0:
        print("0")
    else:
        print("5")
else:
    print("Other")
Output
Enter a number: 25
5
  • 25 % 5 == 0 is true; 25 % 10 == 0 is false, so the inner else prints 5.
  • Answer: 5
Q5Travel

Multiple Choice Question (MCQ): choose the one correct option.

For the inputs 1, 3, 50, 100 (in that order), what is the result line before "Arrive City B"?

Python
print("Travel from City A to City B")

time = int(input("Enter time: "))
longer = int(input("Define longer: "))

if time >= longer:
    price = int(input("Enter price: "))
    higher = int(input("Define higher: "))

    if price >= higher:
        print("Train")
    else:
        print("Coach")
else:
    price = int(input("Enter price: "))
    higher = int(input("Define higher: "))

    if price >= higher:
        print("Daytime Flight")
    else:
        print("Red Eye Flight")

print("Arrive City B")
1
Train
2
Coach
3
Daytime Flight
4
Red Eye Flight
Solution
Idea

1 >= 3 is false, so use the else branch.

Python
print("Travel from City A to City B")

time = int(input("Enter time: "))
longer = int(input("Define longer: "))

if time >= longer:
    price = int(input("Enter price: "))
    higher = int(input("Define higher: "))

    if price >= higher:
        print("Train")
    else:
        print("Coach")
else:
    price = int(input("Enter price: "))
    higher = int(input("Define higher: "))

    if price >= higher:
        print("Daytime Flight")
    else:
        print("Red Eye Flight")

print("Arrive City B")
Output
Travel from City A to City B
Enter time: 1
Define longer: 3
Enter price: 50
Define higher: 100
Red Eye Flight
Arrive City B
  • time >= longer is false, so the program goes to the else block; 50 >= 100 is false, so Red Eye Flight is printed.
  • Answer: option 4.
Q6Even or odd

Numerical Answer Type (NAT).

What does the even/odd program print for the input 10?

Python
x = int(input("Enter a number: "))
if x % 2 == 0:
    print("Even")
else:
    print("Odd")
Solution
Idea

Check the remainder on division by 2.

Python
x = int(input("Enter a number: "))
if x % 2 == 0:
    print("Even")
else:
    print("Odd")
Output
Enter a number: 10
Even
  • 10 % 2 is 0, so Even.
  • Answer: Even
Revision overview
Problem 1x % 2 == 0
Even else Odd
Problem 2Nested: % 5 then % 10
0, 5 or Other
Problem 3elif chain, order matters
60 → D, 105 → B (bug)
Practice zoneWeek 2 · Part 5
Problem 4Two nested decisions
time then price
MethodTrace a table of inputs
TestBoundary values
Revision: turning a decision rule into if/elif/else code
Next · ModulesImporting Modules: math, random, calendar
06
Modules

Importing Modules: math, random, calendar

Reusing code with import, and the four ways of importing.

A module is reusable code that you can bring into your program with import. It saves you from rewriting common tools.

6.1Importing modules

Python
import math
print(math.pow(10, 3))
Output
1000.0

Use from to import a particular part of a module; then you use the name directly, without the math. prefix.

Python
from math import sqrt
print(sqrt(9))
Output
3.0

6.2The math module

NameWhat it givesSample
math.sqrt(x)square root of x3.0
math.pow(x, y)x raised to the power y (float)8.0
math.ceil(x)rounds up to an integer3
math.floor(x)rounds down to an integer2
math.pithe constant π3.141592653589793
math.ethe constant e2.718281828459045
math.cos(x) sin(x) tan(x)trigonometric functions (x in radians)1.0 0.0 0.0
Python
import math
print(math.sqrt(9))
print(math.pow(2, 3))
x = math.ceil(2.6)
y = math.floor(2.6)
print(x)
print(y)
Output
3.0
8.0
3
2
Python
import math
print(math.pi)
print(math.e)
print(math.cos(0))
print(math.sin(0))
print(math.tan(0))
Output
3.141592653589793
2.718281828459045
1.0
0.0
0.0
Watch the types. sqrt and pow return floats (3.0, 8.0), while ceil and floor return integers.

Extra: for a negative number, floor goes to the smaller integer, which is not the same as cutting off the decimal part.

Python
import math
print(math.floor(-2.6))
print(math.ceil(-2.6))
print(int(-2.6))
Output
-3
-2
-2

6.3The random module

  • random.random() gives a random float from 0.0 up to (but not including) 1.0.
  • random.randint(x, y) gives a random integer in the range x to y; both ends can occur.
Python
import random
x = random.random()
print(x)
y = random.randint(1, 10)
print(y)

The printed values change every run, so the exact output cannot be predicted. What you can predict are the ranges:

Python
import random
x = random.random()
y = random.randint(1, 10)
print(0 <= x < 1)
print(1 <= y <= 10)
print(type(x), type(y))
Output
True
True
<class 'float'> <class 'int'>

6.4The calendar module

Python
import calendar
print(calendar.month(2020, 10))
Output
    October 2020
Mo Tu We Th Fr Sa Su
          1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

calendar.month(year, month) returns the text of one month; the week starts on Monday. calendar.calendar(year) returns the whole year. Here are the first lines of calendar.calendar(2018):

Python
import calendar
lines = calendar.calendar(2018).splitlines()
print("\n".join(lines[:6]))
Output
                                  2018

      January                   February                   March
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
 1  2  3  4  5  6  7                1  2  3  4                1  2  3  4
 8  9 10 11 12 13 14       5  6  7  8  9 10 11       5  6  7  8  9 10 11

6.5Different ways of importing modules

import stylethen usenoteimport mathmath.sqrt(4)name stays math.from math import sqrtsqrt(4)only sqrtimport math as mm.sqrt(4)short alias mfrom math import *sqrt(4)avoid: floods names
Figure 10. Four import forms and how to call sqrt after each
Python
# 1. Whole module
import math
print(math.sqrt(4))

# 2. Specific item
from math import sqrt
print(sqrt(4))

# 3. Alias
import math as m
print(m.sqrt(4))

# 4. Everything
from math import *
print(sqrt(4))
Output
2.0
2.0
2.0
2.0
FormUseNote
import mathmath.sqrt(4)safest; the module name shows where a function comes from
from math import sqrtsqrt(4)only the named item is brought in
import math as mm.sqrt(4)short alias for a long name
from math import *sqrt(4)brings in everything; can overwrite your own names
Python
import math
print(sqrt(4))
Error
NameError: name 'sqrt' is not defined
Python
from math import sqrt
print(math.sqrt(4))
Error
NameError: name 'math' is not defined

A name only exists in the form you imported it. After import math you must write math.sqrt; after from math import sqrt the name math itself is not defined. Both mistakes give a NameError.

6.6Going deeper

  • Imports usually go at the top (extra). It makes clear what a program depends on.
  • pow versus ** (extra). math.pow(2, 3) returns a float 8.0, while 2 ** 3 returns the integer 8.
  • Why avoid import * (extra). If two modules define the same name, the later one silently wins.
Python
import math
print(math.pow(2, 3))
print(2 ** 3)
Output
8.0
8

6.7Exam tips and common mistakes

Exam tips
  • Match the way you call a function to the way you imported it.
  • For random functions, reason about the range, never about the exact value.
Common mistakes
  • Calling sqrt(4) after only import math.
  • Calling math.sqrt after from math import sqrt.
  • Thinking random.randint(1, 10) never returns 10.
  • Passing degrees to sin and cos; they expect radians.

Practice questions (graded-assignment style)

Q1pow

Numerical Answer Type (NAT).

What does the program print?

Python
import math
print(math.pow(2, 3))
Solution
Idea

math.pow returns a float.

Python
import math
print(math.pow(2, 3))
Output
8.0
  • 2 raised to 3 is 8, and pow returns the float 8.0.
  • Answer: 8.0
Q2ceil and floor

Numerical Answer Type (NAT).

What does the program print?

Python
import math
print(math.ceil(2.6) + math.floor(2.6))
Solution
Idea

Round 2.6 up and down, then add.

Python
import math
print(math.ceil(2.6) + math.floor(2.6))
Output
5
  • ceil(2.6) is 3 and floor(2.6) is 2: 3 + 2 = 5.
  • Answer: 5
Q3Which import?

Multiple Choice Question (MCQ): choose the one correct option.

What happens when this runs?

Python
import math
print(sqrt(4))
1
It prints 2.0
2
It prints 4
3
It raises a NameError
4
It raises a SyntaxError
Solution
Idea

Which name did the import create?

Python
import math
print(sqrt(4))
Error
NameError: name 'sqrt' is not defined
  • import math creates the name math, not sqrt, so sqrt(4) is a NameError.
  • Answer: option 3.
Q4Imports that work

Multiple Select Question (MSQ): select all that apply.

For which setups does print(sqrt(4)) print 2.0?

1
import math
2
from math import sqrt
3
import math as m
4
from math import *
Solution
Idea

Which setups bring the bare name sqrt in?

  • from math import sqrt and from math import * bring in sqrt itself.
  • import math needs math.sqrt, and the alias form needs m.sqrt.
  • Answer: options 2 and 4.
Q5Random ranges

Multiple Choice Question (MCQ): choose the one correct option.

Which statement about the program is always true?

Python
import random
x = random.random()
y = random.randint(1, 10)
print(0 <= x < 1)
print(1 <= y <= 10)
1
The first line printed is always 0.5
2
Both printed lines are True
3
The second line can be False when the integer is 10
4
The program raises an error
Solution
Idea

Think about the ranges, not the values.

Python
import random
x = random.random()
y = random.randint(1, 10)
print(0 <= x < 1)
print(1 <= y <= 10)
Output
True
True
  • random.random() is at least 0 and below 1; randint(1, 10) is between 1 and 10 including both ends.
  • Answer: option 2.
Q6Lines in a month

Numerical Answer Type (NAT).

How many lines does calendar.month(2020, 10) print?

Python
import calendar
print(len(calendar.month(2020, 10).splitlines()))
Solution
Idea

Title line, weekday line, then the weeks.

Python
import calendar
print(len(calendar.month(2020, 10).splitlines()))
Output
7
  • One title line, one weekday-header line and five week lines make 7.
  • Answer: 7
Revision overview
importimport math
math.sqrt(...)
mathsqrt pow ceil floor
pi e cos sin tan
randomrandom(): [0, 1)
randint(x, y): x to y
ModulesWeek 2 · Part 6
calendarmonth(y, m)
calendar(y)
Import styleswhole, from, alias, *
CarefulCall matches import
avoid import *
Revision: reusing code with modules
Next · All partsWeek 2 Summary Sheet
07
All parts

Week 2 Summary Sheet

One page to revise all of Week 2: topics, tools, the exam checklist and the mistakes to avoid.

The big picture

Part 1 · Variables
  • Meaningful names; # comments.
  • Dynamic typing; naming rules; del; short-hand operators.
Part 2 · Operators and strings
  • in / not in; chained comparisons.
  • Escapes \n \t; single, double, triple quotes.
Part 3 · String methods
  • Case, checks, trim, search, replace.
  • Caesar cipher: alpha[(index + k) % 26].
Part 4 · Conditions
  • if, else, elif, nested, ternary.
  • and / or combine tests.
Part 5 · Practice
  • Even/odd, last digit, grades, travel.
  • Order of elif decides edge cases.
Part 6 · Modules
  • import, math, random, calendar.
  • Four import styles.

Revision sheet

TopicKey point
Meaningful variablesnames should communicate purpose
Comments# ; not executed
Dynamic typinga variable can refer to different types
Variable rulesletter/underscore start; case-sensitive; no keywords
Multiple assignmentx, y = 1, 2
Same-value assignmentx = y = z = 8
Deletedel x
Short-handx += 3 etc.
Membershipin, not in
Chained comparisonsa < b < c
Escape characters\n, \t, escaped quotes
Quotessingle, double, triple
String methodscase, checks, trimming, searching, replacing
Caesar Ciphershift letters; % 26 wraps
if / else / elifrun a block / alternative / more conditions
Nested ifif inside if
Conditional expressiona if condition else b
importbring a module into the program
mathmathematical functions/constants
randomrandom values
calendarcalendar output

Which tool when?

You want to…Use
test if a word is inside a textin
check a value lies between two numbersa < x < b
print a quote or a tab inside a string\" \' \t
make a string lowercase / title-caselower() title()
test if a string is all digitsisdigit()
shift a letter and wrap past z% 26
choose between two values on one linea if cond else b
use square root, ceiling, pimath

Exam checklist (from the source)

  • Explain dynamic typing.
  • Apply variable naming rules.
  • Perform multiple assignment and unpacking.
  • Delete a variable using del.
  • Use short-hand assignment operators.
  • Use in and not in.
  • Read chained comparisons.
  • Use \n, \t and escaped quotes.
  • Distinguish single, double and triple-quoted strings.
  • Know the Week 2 string methods.
  • Explain the Caesar Cipher formula.
  • Write if, if-else and if-elif-else.
  • Combine conditions with and and or.
  • Write a nested if and the conditional expression.
  • Import and use modules; know the different import styles.
  • Use math.sqrt(), pow(), ceil(), floor(), random.random(), random.randint() and the calendar module.

Common mistakes

Invalid names
  • 2nd_place, first-name and keywords are not allowed.
Methods change nothing
  • String methods return a new string; assign it back.
Wrong branch order
  • A broad elif before a narrow one hides the narrow one.
= versus ==
  • Compare with ==; = assigns.
Import mismatch
  • Call a function the way you imported it.
Unvalidated input
  • The grade program prints B for 105; check the range first.
Back to top