This document contains hints and solutions for all exercises. Try to complete them yourself first!
- Attempt the exercise on your own
- If stuck, check the hints section
- Only look at solutions as a last resort
- Run the tests to verify your solutions
Exercise 1.1 Solution
greeting = "Hello, Python!"
year = 2026
pi_value = 3.14159
is_learning = True
nothing = NoneExercise 1.2 Solution
# Part A: Using type()
hello_type = type("hello") # Returns str
answer_type = type(42) # Returns int
pi_type = type(3.14) # Returns float
flag_type = type(True) # Returns bool
empty_type = type(None) # Returns NoneType
# Part B: Using isinstance()
is_string = isinstance("hello", str) # True
is_integer = isinstance(3.14, int) # False - it's a float!
is_numeric = isinstance(42, (int, float)) # True - checks multiple types
is_none = isinstance(None, type(None)) # TrueWhen to use which:
type(x) == SomeType- exact type match onlyisinstance(x, SomeType)- preferred in most cases, works with inheritanceisinstance(x, (Type1, Type2))- check against multiple types
Exercise 1.3 Solution
converted_int = int(number_string)
truncated_int = int(float_number)
zero_as_bool = bool(some_number)
nonzero_as_bool = bool(non_zero)Exercise 1.4 Solution
f_string_greeting = f"Hello, {name}!"
multi_line = """Line 1
Line 2
Line 3"""Exercise 1.5 Solution
stripped = text.strip()
lowered = text.lower()
replaced = text.replace("Python", "JavaScript")
split_list = parts.split(", ")Solutions
# 2.1
power_result = 2 ** 10
regular_division = 17 / 5
integer_division = 17 // 5
remainder = 17 % 5
# 2.2
int_float_equal = 10 == 10.0 # True
string_int_equal = "5" == 5 # False
not_equal = 10 != 5 # True
# 2.3
and_result = a and b
or_result = a or b
not_result = not a
# 2.4
equal_value = list1 == list2
same_object_1_2 = list1 is list2
same_object_1_3 = list1 is list3
is_none = value is None
# 2.5
three_in_list = 3 in numbers
ten_not_in_list = 10 not in numbers
python_in_message = "Python" in message
name_in_dict = "name" in person
alice_in_dict = "Alice" in person
# 2.6
if (length := len(data)) > 5:
result_walrus = f"List has {length} items"Solutions
# 1.1
mixed = [1, "two", 3.0, True, None]
first = mixed[0]
last = mixed[-1]
second_to_last = mixed[-2]
# 1.2
slice_1 = numbers[2:5]
slice_2 = numbers[:3]
slice_3 = numbers[-3:]
every_other = numbers[::2]
reversed_list = numbers[::-1]
# 1.3
fruits.append("cherry")
fruits.insert(0, "apricot")
removed_last = fruits.pop()
removed_first = fruits.pop(0)
# 1.4
concatenated = list_a + list_b
repeated = [1, 2, 3] * 3
length = len(list_a)
contains_two = 2 in list_a
# 1.5
x, y, *remaining = coordinates
first_coord, *_, last_coord = coordinates
# 1.6
sorted_new = sorted(unsorted)
to_sort.sort()
reverse_sorted = sorted(unsorted, reverse=True)Solutions
# 2.1
person = {"name": "Alice", "age": 30, "city": "New York"}
name = person["name"]
age = person.get("age")
country = person.get("country", "Unknown")
# 2.2
user["role"] = "admin"
user["email"] = "[email protected]"
removed_username = user.pop("username")
# 2.3
keys = list(inventory.keys())
values = list(inventory.values())
items = list(inventory.items())
has_apples = "apples" in inventory
# 2.4
formatted_scores = [f"{k}: {v}" for k, v in scores.items()]
# 2.5
merged = {**defaults, **user_prefs}
# 2.6
doubled_prices = {k: v * 2 for k, v in prices.items()}
expensive = {k: v for k, v in prices.items() if v >= 0.75}
# 2.7
alice_role = company["employees"]["alice"]["role"]
bob_salary = company["employees"]["bob"]["salary"]
company["employees"]["charlie"] = {"role": "manager", "salary": 90000}
# 2.8 - .get() vs .setdefault()
# Part A: .get() returns default but doesn't modify dict
theme_value = config.get("theme", "light") # Returns "dark" (exists)
timeout_value = config.get("timeout", 30) # Returns 30 (missing, default)
# Part B: .setdefault() returns value AND inserts if missing
name_from_setdefault = user_settings.setdefault("name", "Unknown") # Returns "Alice"
role_from_setdefault = user_settings.setdefault("role", "guest") # Returns "guest" AND adds it
# Part C: Grouping pattern with setdefault
for word in words_to_group:
first_letter = word[0]
grouped_words.setdefault(first_letter, []).append(word)
# Part D: Counting with .get()
for word in words:
word_count[word] = word_count.get(word, 0) + 1Solutions
# 3.1
coordinates = (10, 20, 30)
single = (42,)
point = 5, 10
# 3.2
red = rgb[0]
r, g, b = rgb
new_rgb = (200, rgb[1], rgb[2])
# 3.3
locations = {(0, 0): "origin", (10, 20): "point A"}
origin_name = locations[(0, 0)]
# 3.4
Person = namedtuple('Person', ['name', 'age', 'city'])
alice_age = alice.age
alice_city = alice.city
# 3.5
numbers_set = {1, 2, 3, 4, 5}
unique_numbers = set([1, 2, 2, 3, 3, 3, 4])
empty_set = set()
# 3.6
union = set_a | set_b
intersection = set_a & set_b
difference = set_a - set_b
symmetric_diff = set_a ^ set_b
# 3.7
fruits_set.add("cherry")
fruits_set.add("apple")
fruits_set.remove("banana")
has_apple = "apple" in fruits_set
# 3.8
unique_ordered = list(dict.fromkeys(items_with_dupes))
common = set(list1) & set(list2)
# 3.9
even_squares = {x**2 for x in numbers if x % 2 == 0}
# 3.10
frozen = frozenset({1, 2, 3})Solutions
def get_grade(score):
if score >= 90:
return "A"
elif score >= 80:
return "B"
elif score >= 70:
return "C"
elif score >= 60:
return "D"
else:
return "F"
def is_truthy(value):
return bool(value)
def absolute_value(n):
return n if n >= 0 else -n
def can_vote(age, is_citizen, is_registered):
return age >= 18 and is_citizen and is_registered
def can_enter_club(age, has_id, is_vip):
return (age >= 21 and has_id) or is_vip
def is_valid_percentage(value):
return 0 <= value <= 100
def is_between(value, low, high):
return low < value < high
def http_status_message(code):
match code:
case 200: return "OK"
case 201: return "Created"
case 400: return "Bad Request"
case 401: return "Unauthorized"
case 404: return "Not Found"
case 500: return "Internal Server Error"
case _: return "Unknown Status"
def describe_point(point):
match point:
case (0, 0): return "origin"
case (0, y): return "on y-axis"
case (x, 0): return "on x-axis"
case (x, y) if x == y: return "on diagonal"
case (x, y): return f"point at ({x}, {y})"
def process_user(user):
if user is None:
return "No user provided"
if "name" not in user:
return "Invalid user: no name"
if user["name"] == "":
return "Invalid user: empty name"
if not user.get("active", True):
return "User is inactive"
return f"Processing: {user['name']}"Key Solutions
# Loops
def sum_to_n(n):
total = 0
for i in range(1, n + 1):
total += i
return total
def find_index(items, target):
for index, item in enumerate(items):
if item == target:
return index
return -1
def combine_names(first_names, last_names):
return [f"{first} {last}" for first, last in zip(first_names, last_names)]
# Comprehensions
squares = [x**2 for x in range(1, 11)]
evens = [x for x in range(1, 21) if x % 2 == 0]
flattened = [item for row in matrix for item in row]
num_to_square = {x: x**2 for x in range(1, 6)}
first_letters = {word[0] for word in words_set}
square_gen = (x**2 for x in range(1, 11))Key Solutions
def greet(name):
return f"Hello, {name}!"
def append_to_list(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
def min_max(numbers):
if not numbers:
return (None, None)
return (min(numbers), max(numbers))
double = lambda x: x * 2
is_positive = lambda x: x > 0
multiply = lambda x, y: x * y
def apply_operation(x, y, operation):
return operation(x, y)
def make_multiplier(factor):
def multiplier(x):
return x * factor
return multiplierFor remaining exercises, the key patterns are:
- Use
super().__init__()to call parent constructors @propertyfor getters,@name.setterfor setters__str__for human-readable,__repr__for debugging
try/except/else/finallyfor clean error handlingraise ValueError("message")to raise exceptionsraise NewError() from originalfor exception chaining
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
# before
result = func(*args, **kwargs)
# after
return result
return wrapperdef generator():
yield value # yields one at a time
# Generator expression
gen = (x**2 for x in range(10))class MyContext:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
return False # Don't suppress exceptions
@contextmanager
def my_context():
# setup
yield resource
# cleanupEach exercise file has built-in tests. Run them with:
python3 filename.pyFor pytest exercises:
pip install pytest
pytest 13-testing/01_pytest_basics.py -v- Read the Python documentation: https://docs.python.org/3/
- Try the exercise in a Python REPL first
- Use
print()statements to debug - Check error messages carefully - they're usually helpful!