Exercises - functools
Exercises — functools
Section titled “Exercises — functools”partial Exercises
Section titled “partial Exercises”Exercise 1 — 🟢 Beginner
Using partial, create two functions from a base multiply function: one that doubles a number and one that triples it.
def multiply(x, factor): return x * factor
# expected:# double(5) → 10# triple(5) → 15Exercise 2 — 🟢 Beginner
Using partial, create a greet_formally and greet_casually function from a base greet function.
def greet(style, name): if style == "formal": return f"Good day, {name}." return f"Hey, {name}!"
# expected:# greet_formally("Alice") → "Good day, Alice."# greet_casually("Alice") → "Hey, Alice!"Exercise 3 — 🟡 Intermediate
Using partial and map, convert a list of temperatures from Celsius to Fahrenheit without using a lambda.
def convert(unit, value): if unit == "fahrenheit": return (value * 9 / 5) + 32
celsius = [0, 10, 20, 30, 40]# expected output: [32.0, 50.0, 68.0, 86.0, 104.0]lru_cache / cache Exercises
Section titled “lru_cache / cache Exercises”Exercise 4 — 🟢 Beginner
Add memoization to this slow function using lru_cache and verify the cache is being used.
import time
def slow_square(n): time.sleep(1) # simulates expensive computation return n ** 2
# expected:# first call: slow_square(5) → takes ~1 second# second call: slow_square(5) → instant (cached)# slow_square.cache_info() → hits=1, misses=1Exercise 5 — 🟡 Intermediate
Use lru_cache to memoize a recursive function that computes the nth triangular number (sum of all integers from 1 to n).
# triangular(1) = 1# triangular(2) = 3 (1 + 2)# triangular(3) = 6 (1 + 2 + 3)# triangular(4) = 10 (1 + 2 + 3 + 4)
# expected:# triangular(10) → 55# triangular(100) → 5050Exercise 6 — 🟡 Intermediate
Implement a memoized function that counts how many ways you can climb a staircase of n steps, taking either 1 or 2 steps at a time.
# climb(1) → 1 (only one way: [1])# climb(2) → 2 ([1,1] or [2])# climb(3) → 3 ([1,1,1], [1,2], [2,1])# climb(4) → 5
# expected:# climb(10) → 89# climb(30) → 1346269total_ordering Exercises
Section titled “total_ordering Exercises”Exercise 7 — 🟢 Beginner
Create a Temperature class using total_ordering that compares temperatures by their value. Define only __eq__ and __lt__, and verify the auto-generated methods work.
t1 = Temperature(100)t2 = Temperature(200)
# expected:# t1 < t2 → True# t1 > t2 → False ← auto-generated# t1 <= t2 → True ← auto-generated# t1 >= t2 → False ← auto-generatedExercise 8 — 🟡 Intermediate
Create a Card class representing a playing card using total_ordering. Cards should be ordered by rank (2 lowest, Ace highest). Suit does not affect ordering.
ranks = ['2','3','4','5','6','7','8','9','10','J','Q','K','A']
c1 = Card('2', 'Hearts')c2 = Card('A', 'Spades')c3 = Card('K', 'Clubs')
# expected:# c1 < c2 → True# c2 > c3 → True# sorted([c2, c1, c3]) → [Card(2), Card(K), Card(A)]Exercise 9 — 🔴 Advanced
Create a SemanticVersion class using total_ordering that parses version strings and compares them correctly.
v1 = SemanticVersion("1.2.0")v2 = SemanticVersion("1.10.0")v3 = SemanticVersion("2.0.0")
# expected:# v1 < v2 → True (1.2 < 1.10 — numeric, not lexicographic!)# v2 < v3 → True# sorted(["2.0.0", "1.10.0", "1.2.0"]) → ["1.2.0", "1.10.0", "2.0.0"]singledispatch Exercises
Section titled “singledispatch Exercises”Exercise 10 — 🟢 Beginner
Use singledispatch to create a describe function that returns a different description depending on the type of the argument.
# expected:# describe(42) → "A number: 42"# describe("hello") → "A string of 5 characters"# describe([1, 2, 3]) → "A list of 3 items"# describe(3.14) → TypeError: Unsupported typeExercise 11 — 🟡 Intermediate
Use singledispatch to create a serialize function that converts different types to a JSON-friendly string representation.
from datetime import date
# expected:# serialize(42) → "42"# serialize(3.14) → "3.14"# serialize("hello") → '"hello"'# serialize([1, 2, 3]) → "[1, 2, 3]"# serialize(date(2024, 1, 1)) → "2024-01-01"Exercise 12 — 🔴 Advanced
Use singledispatch to create a flatten function that recursively flattens nested structures of mixed types into a single list.
# expected:# flatten(1) → [1]# flatten("hi") → ["hi"]# flatten([1, [2, 3]]) → [1, 2, 3]# flatten([1, [2, [3, [4]]]]) → [1, 2, 3, 4]# flatten((1, (2, 3))) → [1, 2, 3] ← tuples tooTry solving each exercise using only the relevant functools tool — resist reaching for a lambda or a loop where partial, cache, or singledispatch would express the intent more clearly.