Programming in Python · Lessons 5–8
Programming in Python Study Guide: Lessons 5–8
Review characters and strings, decision control structures, loops, lists, and dictionaries for Lessons 5–8.
How to use this guide
This guide condenses Lessons 5–8 into the vocabulary, comparisons, and code patterns you need to read, trace, and complete short Python programs. Read the lesson sections in order, trace every example by hand, and then write a small variation without copying it.
Study in this order:
- Explain each bold term in your own words.
- Compare the terms that are easy to confuse.
- Predict what each code sample displays before running it.
- Practice filling in a missing line: given the output, decide which statement produces it.
The ideas that connect Lessons 5–8
The lessons build on one another. Lesson 5 gives you text data and the operators and methods that work on it. Lesson 6 lets a program choose which statements to run. Lesson 7 lets a program repeat statements. Lesson 8 stores many values under one name so that loops and decisions can process the whole collection.
Keep these distinctions connected:
- Indexes start at 0 for strings and lists. The last index is always one less than the length.
- Stop before the end: a slice
s[3:8]andrange(3, 8)both stop just before 8. =assigns a value;==compares two values.input()always returns a string. Useint()orfloat()before comparing to a number, doing arithmetic, or passing the value torange().- A colon and indentation mark every block:
if,elif,else,for, andwhile. - An accumulator is initialized before a loop and updated inside it.
- Strings are immutable (methods return a new string); lists and dictionaries are mutable (they can be changed in place).
Lesson 5 — Character and String Data Types
Characters
A character is a single letter of the alphabet, a single numeral from 0 to 9, or a symbol. Python has no separate character type; a character is a string of length 1. By convention in this course, character and string literals are surrounded by double quotes.
middle_initial = "S"
The quotes are not stored; they only mark where the literal begins and ends. Without quotes, S would be treated as a variable name.
ASCII and memory
Character data is stored as a numeric code. ASCII assigns an eight-bit code to each character, so one ASCII character uses 1 byte of memory. The letter a is 97 (01100001).
| Value | Type | Stored as |
|---|---|---|
"5" |
string (character) | ASCII code for the symbol 5: 00110101 |
5 |
integer | the binary number five: 00000101 |
Digits are stored as ASCII codes, but integers are stored as binary numbers. Data used in calculations should be stored as a numeric type.
print("2" + "5") # 25 (strings are joined)
print(2 + 5) # 7 (integers are added)
Output on one line or separate lines
high_five = "5"
lucky_seven = "7"
print(high_five, lucky_seven) # 5 7 (comma adds a space)
print(high_five + " " + lucky_seven) # 5 7 (you supply the space)
print(high_five) # separate print() calls
print(lucky_seven) # put values on separate lines
Strings and memory
A string is a sequence of alphanumeric characters enclosed in quotation marks. Strings are stored in consecutive (successive) memory locations, one character per location, and each character has an index starting at 0.
| Character | P | u | m | p | k | i | n |
|---|---|---|---|---|---|---|---|
| Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
"Pumpkin"[4] is "k". An index past the end causes an IndexError. A string is data; it does not embed or run commands.
Escape sequences
An escape sequence begins with a backslash and places a special character inside a string. Use \" when string data includes quotation marks.
| Escape sequence | Meaning |
|---|---|
\" |
quotation mark |
\\ |
backslash |
\n |
newline |
\t |
tab |
fun_fact = "Philip Parker wrote the song \"Alphabet Soup.\""
String functions and methods
Common string tasks are finding the length, changing the case, checking whether a string contains a character, and retrieving a substring.
| Tool | Purpose | Example | Result |
|---|---|---|---|
len(s) |
length as an integer (a function, not s.length()) |
len("Soup") |
4 |
upper() |
uppercase copy | "s".upper() |
"S" |
lower() |
lowercase copy | "QUIET".lower() |
"quiet" |
title() |
capitalize each word | "hello world".title() |
"Hello World" |
isalpha() |
is it a letter? | "a".isalpha() |
True |
isdigit() |
is it a digit? | "2".isdigit() |
True |
find() |
index of first occurrence, or -1 |
"Blueberry muffin".find(" ") |
9 |
count() |
number of occurrences | "banana".count("a") |
3 |
String methods never change the original string, because strings are immutable. Assign the result to keep it:
speech = "QUIET"
speech = speech.lower()
print(speech) # quiet
find() can locate a space so a program can later break a string into separate words.
Case sensitivity
"Soup", "SOUP", and "soup" are different strings because uppercase and lowercase letters have different codes. Case matters when searching and sorting data, comparing passwords, and naming variables. Normalize case before comparing:
if first_item.lower() == second_item.lower():
print("The words are the same.")
Substrings (slices)
Retrieve a substring by giving a start and end index. The ending index is not included.
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
print(alphabet[3:8]) # DEFGH
Concatenation
Concatenation chains two or more strings in sequence using the + operator. Use it to combine values stored in different variables, such as a first and last name.
color = input("What is your favorite color? ")
animal = input("What is your favorite animal? ")
print("Our", animal + " mug comes in " + color)
Best practice: store a concatenated result in a new, clearly named variable.
product_name = company_name + " " + soup_name
Coercion and typecasting
Python can concatenate strings with other strings and characters, but not with integers or floats. Concatenating a string with integer data is an invalid string operation and raises a TypeError.
- Coercion is automatic conversion by the language (JavaScript does this; Python does not for
+). - Typecasting is an explicit conversion written by the programmer.
house_number = 101
full_address = str(house_number) + " Main Street" # int to string
day_number = int("15") # string to int
Lesson 5 terms to know
character, character literal, string, string literal, ASCII, byte, index, IndexError, escape sequence, \", \n, len(), upper(), lower(), title(), isalpha(), isdigit(), find(), count(), immutable, case sensitivity, substring, slice, concatenation, coercion, typecasting, str(), int()
Lesson 6 — Decision Control Structures
Control structures
A control structure alters the sequential execution of statements in a program. A decision control structure branches to specific statements based on a condition. Algorithms need decisions when data must be handled differently based on its value, such as voting eligibility, thermostat control, or shipping costs. A task that treats every item the same way, such as assigning the same grade to everyone, does not need a decision.
The four decision structures are if-then, if-then-else, nested-if, and else-if.
Flowcharts and pseudocode
- A diamond shows a decision point in a flowchart.
- In an if-then flowchart, the True branch contains statements and the False branch bypasses them.
- In an if-then-else flowchart, both branches contain statements, and exactly one runs.
- In pseudocode, the conditional statement begins with if, and the statements in each branch are indented.
if choice = 1
output "Great! Let's begin."
else
output "You chose to quit."
The conditional statement
A conditional statement directs program flow when a condition is true. In Python it ends with a colon, and the block below it is indented.
choice = input("begin the exam: ")
if choice == "Y": # the conditional statement
print("You entered " + choice)
print("Good luck!") # runs either way
Because input() returns a string, compare to "1" in quotes, or convert with int() first.
Relational operators
A relational operator compares two operands.
| Operator | Meaning |
|---|---|
== |
equal to |
!= |
not equal to |
< |
less than |
> |
greater than |
<= |
less than or equal to |
>= |
greater than or equal to |
If monthly_rainfall = 19, then monthly_rainfall != 18 is True and monthly_rainfall > 20 is False.
= versus ==: = places a value in a variable; == checks whether two operands are equal in content. Using = inside a condition is a syntax error.
Boolean expressions and Boolean data
A Boolean expression evaluates to True or False and is used in a conditional statement. The Boolean data type is used when declaring or assigning a variable. True and False are capitalized.
paid_in_full = True # Boolean variable (assignment)
loves_pie = True
if loves_pie: # the variable is the Boolean expression
print("Would you like some pie?")
if-then-else
bev_type = input()
if bev_type == "1":
print("You chose caffeinated.")
else:
print("You chose non-caffeinated.")
else sits at the same indent level as if, has a colon, and has no condition.
Nested-if
A nested-if is a decision inside another decision. Use a second indent level for the inner structure so it is easy to trace.
if choice == "0":
sure_thing = input("Are you sure? ")
if sure_thing == "y":
print("Disconnecting.")
else:
print("Connecting you to the help desk.")
else:
print("Connecting you now.")
else-if (elif)
Use elif for three or more paths. Conditions are evaluated only until one is true; the remaining branches are skipped.
if choice == 1:
print("One")
elif choice == 2:
print("Two")
elif choice <= 2:
print("Daisy")
else:
print("Stop")
When choice is 2, the output is only Two.
Fall through means execution continues to the next conditional statement within a structure. Python’s if/elif structure does not fall through, so order conditions from most specific to least specific.
Logical operators
A logical operator combines Boolean expressions.
| Operator | Result is True when |
Example |
|---|---|---|
and |
both conditions are true | choice > 3 and choice != 9 |
or |
at least one condition is true | purchase > 100.00 or vip |
not |
flips a Boolean value to its opposite | not clearance |
Truth tables for and and or:
| A | B | A and B |
A or B |
|---|---|---|---|
True |
True |
True |
True |
True |
False |
False |
True |
False |
True |
False |
True |
False |
False |
False |
False |
Use parentheses when mixing operators so the logic runs in the intended order:
if (final_exam_grade >= 80) or (attendance == 100.00 and submissions == 100.00):
final_grade = final_grade * 1.05
Trace practice: with if rain > 80.00 or temp < 50:, a value of rain = 20.00 and temp = 60 makes both conditions false, so the else branch runs. With and, both conditions must be true (for example, rain = 85.00 and temp = 40).
Lesson 6 terms to know
control structure, decision control structure, flowchart, diamond, pseudocode, conditional statement, if-then, if-then-else, nested-if, else-if, elif, else, relational operator, ==, !=, assignment operator, Boolean expression, Boolean data type, True, False, fall through, logical operator, and, or, not, truth table
Lesson 7 — Repetition Control Structures
Loop basics
A repetition control structure (loop) repeats a block of code. Loops are useful for processing a series of records or list items, keeping a running count, accumulating totals, and solving recursive math problems.
| Loop type | Python keyword | Use when |
|---|---|---|
| Count-controlled loop | for |
you know how many times to repeat, every time the program runs |
| Pre-test (condition-controlled) loop | while |
repetition depends on a condition, such as validating input |
range() and iterative sequences
An iterative sequence is data that can be traced linearly, one item at a time. range(start, end, increment) creates a numeric sequence. Start defaults to 0, increment defaults to 1, and the end is never included.
| Call | Sequence |
|---|---|
range(5) |
0 1 2 3 4 |
range(1, 4) |
1 2 3 |
range(4, 12) |
4 5 6 7 8 9 10 11 |
range(2, 11, 2) |
2 4 6 8 10 |
For-loops
for i in range(1, 4):
print("Hip, hip, hooray!") # runs three times
In for i in range(1, 3):, i is the loop counter, and range(1, 3) supplies the sequence that acts as the loop’s test condition. The range() call controls how many times the loop repeats.
Pseudocode for a for-loop uses wording such as:
repeat three times:
Display "Math is Fun"
Avoid using or changing the loop counter in other statements inside the loop; doing so can inadvertently change the counter. Use a separate variable instead.
User-controlled loops
A user-controlled loop gets its repetition count from input at runtime.
scoops = int(input("How many scoops today? "))
for i in range(scoops):
print("Serving one scoop.")
int() is required because range() needs an integer.
Counters and accumulators
A counter counts in a pattern, such as counting by twos. An accumulator builds a running total in two steps: initialize it before the loop, then add to it inside the loop.
total_weight = 0
weight = 15
for i in range(3):
total_weight = total_weight + (weight * 2) # the accumulator
print(total_weight) # 90
Nested loops
A nested loop is a loop inside another loop. The computer runs one outer iteration, then the entire inner loop, then the next outer iteration. Each loop needs its own counter; programmers typically use i for the outer loop and j for the inner loop.
total_weight = 0
for s in range(sets):
print("Set:", s)
for r in range(reps):
total_weight = total_weight + (weight * 2)
print(" Rep:", r, "Progress:", total_weight, "lbs.")
The accumulator is not reset between sets, so the running total keeps growing. With 10-pound weights, each rep adds 20 pounds: after Set 1 has 8 reps (160 lbs), Set 2 continues at 180, 200, and so on.
Pre-test loops (while-loops)
A pre-test loop begins with a condition and runs only while that condition is true. In a flowchart, it starts with the condition. Pre-test loops are especially effective for validating input.
muffins = int(input("Enter the number of muffins: "))
while muffins < 12 or muffins > 48:
muffins = int(input("Try again. You can order 12-48 muffins: "))
print("Okay. You ordered", muffins, "muffins.")
The new input must be assigned back to the variable the condition checks.
Infinite loops and break
An infinite loop never ends on its own. It keeps running; it does not halt the program early. Common causes are a condition that can never become false, failing to store new input, and sharing a counter between nested loops. Press Ctrl+C to stop one in a console application.
A break statement exits a loop immediately, but it can have unintended consequences because execution continues with the statement after the loop. The preferred design builds the exit into the loop’s condition, often with a sentinel value such as 999.
Lesson 7 terms to know
repetition control structure, loop, count-controlled loop, for-loop, range(), iterative sequence, loop counter, control statement, user-controlled loop, counter, accumulator, nested loop, outer loop, inner loop, pre-test loop, while-loop, condition-controlled loop, input validation, infinite loop, Ctrl+C, break, sentinel value
Lesson 8 — Lists
List basics
A list is a data structure that stores a collection of elements; it is a composite data type built from primitive types. A list can hold Booleans, integers, floating-point numbers, or strings.
Three characteristics of a list: heterogeneous (mixed types allowed), ordered (each element has an index), and “infinite” (it can grow as memory allows).
- A one-dimensional list is linear, like one row of values.
- A two-dimensional list looks like a table, grid, or matrix of rows and columns.
A list index is the element’s position, not a random number. For ["J", "A", "W", "S", 3], the first index is 0 and the last is 4.
Creating and changing lists
bucket = [] # empty list
kites_sold = [8, 15, 12, 7, 3, 5, 5] # numeric list
daily_snow = [1, 2, 5, 11, 7, 3, 2] # seven values in order, one variable
kites_sold[3] = 9 # change the fourth element
print(kites_sold[6]) # 5 (last element)
Using an index outside the list produces an index error.
Traversing a list
Traversing means accessing each element in sequence.
game_outcomes = ["Win", "Loss", "Loss", "Win"]
for element in game_outcomes: # element-based traversal
print(element)
for i in range(len(game_outcomes)): # index-based traversal
print(game_outcomes[i])
To modify every element, use an index-based loop that reassigns each element:
for i in range(len(numbers)):
numbers[i] += 1
Collecting list input at runtime
Start with an empty list and call append(). Stop after a known length or when the user enters a sentinel value.
values = []
number = int(input())
while number != -1:
values.append(number)
number = int(input())
List functions and methods
| Tool | Purpose | Example |
|---|---|---|
len() |
number of elements | len(numbers) |
sum() |
total of the elements | sum([1, 2, 5]) is 8 |
min() / max() |
smallest / largest value | max([2, 5, 3]) is 5 |
count() |
how many times a value appears | [2, 3, 3].count(3) is 2 |
index() |
index of the first match | [2, 5, 3].index(5) is 1 |
append() |
add to the end | bucket.append(4) |
sort() |
sort in place | numbers.sort() |
Summing with an accumulator gives the same result as sum():
total = 0
for element in daily_snow:
total += element
Lists can also manipulate the characters in a word or phrase, such as reversing or encrypting them.
List comprehension, filtering, and mapping
List comprehension concisely creates a list by placing for-loop logic inside square brackets.
# Code block A: list comprehension
list_of_ints = [i for i in range(5, 26, 5)]
# Code block B: for-loop
list_of_ints = []
for i in range(5, 26, 5):
list_of_ints.append(i)
Both blocks store [5, 10, 15, 20, 25].
- Filtering keeps only elements that meet a condition and stores them in a new list:
[i for i in range(100) if i % 2 == 0]. - Mapping applies a behavior (an expression or function call) to each element and stores the results in a new list:
[i * 2 for i in range(20)]. - Both together:
[i * 2 for i in range(20) if i % 2 == 0].
Pattern: [expression for item in sequence if condition]. The expression is the mapping; the if is the filtering.
Two-dimensional lists
A two-dimensional list is a list that contains lists. Each element is a variable that can itself be a list. It looks like a grid, but it is not stored as a grid in memory.
paint_box = [["Red", "Orange", "Yellow"],
["Green", "Blue", "Indigo"]]
print(paint_box[1][2]) # Indigo (row 1, column 2)
Traversing requires a nested loop: the outer loop moves through the rows, and the inner loop moves through the columns.
for i in range(len(board)):
for j in range(len(board[i])):
print(board[i][j], end="")
print()
join() glues strings together with a separator:
print("\n".join([" | ".join(row) for row in paint_box]))
Output:
Red | Orange | Yellow
Green | Blue | Indigo
Tic-tac-toe
Place a move by using the player’s row and column inputs as the two indexes:
row = int(input("Row: "))
col = int(input("Column: "))
board[row][col] = "X"
Check for a win on the top row, making sure the cells are not empty:
if board[0][0] != " " and board[0][0] == board[0][1] and board[0][1] == board[0][2]:
print("Winner on the top row!")
Dictionaries
A dictionary stores key: value pairs in curly braces. You provide keys, which are used to look up the associated values.
positions = {"Chad": "1st base", "Cindy": "2nd base", "Tim": "Outfield"}
print(positions["Cindy"]) # read a value by key
positions["Tim"] = "Pitcher" # update an existing key
positions["Josip"] = "Catcher" # add a new key and value
positions.pop("Chad") # remove an entry by key
print(positions.keys()) # all keys, without values
- Assigning to an existing key changes its value; assigning to a new key adds an entry.
- A missing key raises a
KeyError. - Loop over the keys to reach every value:
for key in weekend_specials:
print("The special on", key + " is", weekend_specials[key])
Lesson 8 terms to know
list, data structure, composite data type, primitive data type, element, list index, heterogeneous, ordered, one-dimensional list, two-dimensional list, index error, traverse, element-based traversal, index-based traversal, append(), sentinel value, len(), sum(), min(), max(), count(), index(), sort(), list comprehension, filtering, mapping, nested loop, join(), dictionary, key, value, keys(), pop(), KeyError
Course Notes