Exercises#
This page contains four take-home exercises that reinforce the concepts from Lecture 5. Each exercise asks you to write code from scratch based on a specification – no starter code is provided.
All files should be created inside your lecture5/ workspace folder.
Exercise 1 – First-Class Functions and Lambdas
Goal
Demonstrate your understanding of first-class functions, lambda
expressions, and built-in higher-order functions (map, filter,
sorted).
Specification
Create a file lecture5/lambdas_and_hof.py that implements the
following. Each named function must include type hints and a
Google-style docstring.
``square`` – A lambda function that squares a number. Assign it to a variable called
square. Test:square(5)returns25.``add`` – A lambda function that takes two numbers and returns their sum. Assign it to a variable called
add. Test:add(3, 7)returns10.``is_even`` – A lambda function that checks if a number is even. Returns
Trueif even,Falseotherwise. Assign it to a variable calledis_even. Test:is_even(4)returnsTrue.``to_upper`` – A lambda function that converts a string to uppercase. Assign it to a variable called
to_upper. Test:to_upper("hello")returns"HELLO".Sorting with lambdas – Given a list of tuples representing
(name, age):people = [("Alice", 30), ("Bob", 25), ("Charlie", 35)]
Use
sorted()with a lambda to sort by age (ascending).Use
sorted()with a lambda to sort by name length.
In the if __name__ == "__main__" block, call each function/lambda
with example arguments and print the results with labels.
Expected output:
=== Lambda Functions ===
square(5): 25
add(3, 7): 10
is_even(4): True
is_even(7): False
to_upper("hello"): HELLO
=== Sorting ===
By age: [('Bob', 25), ('Alice', 30), ('Charlie', 35)]
By name length: [('Bob', 25), ('Alice', 30), ('Charlie', 35)]
Deliverables
lecture5/lambdas_and_hof.pyThe program must run without errors and produce output matching the expected format above.
Exercise 2 – Write Your Own Decorators
Goal
Practice writing decorators with *args/**kwargs, using
functools.wraps, and transforming return values.
Specification
Create a file lecture5/custom_decorators.py that implements the
following decorators and test functions. Each decorator and test
function must include type hints and a Google-style docstring.
``greet`` – A decorator that prints
"Hello from <function_name>!"before executing the decorated function. Apply it to a function calledsay_goodbye()that prints"Goodbye!".``repeat_twice`` – A decorator that executes the decorated function two times. Apply it to a function called
print_message()that prints"Hello".``uppercase_result`` – A decorator that converts the return value of a function to uppercase (assumes the function returns a string). Apply it to a function called
get_name()that returns"alice".
All decorators must use @functools.wraps to preserve metadata.
In the if __name__ == "__main__" block, call each decorated
function and print the results with labels.
Expected output:
=== greet decorator ===
Hello from say_goodbye!
Goodbye!
=== repeat_twice decorator ===
Hello
Hello
=== uppercase_result decorator ===
get_name() returned: ALICE
Deliverables
lecture5/custom_decorators.pyThe program must run without errors and produce output matching the expected format above.
Exercise 3 – Closures, Callables, and Partials
Goal
Practice closures with nonlocal, the callable() built-in, and
functools.partial for argument freezing.
Specification
Create a file lecture5/closures_and_partials.py that implements the
following. Each function must include type hints and a Google-style
docstring.
``make_accumulator`` – A closure that takes an initial value and returns a function. Each call to the returned function adds its argument to a running total and returns the new total.
acc = make_accumulator(100) print(acc(10)) # 110 print(acc(20)) # 130
``log_message`` – A general logging function with the signature
log_message(level: str, msg: str) -> strthat returns a formatted string"[<level>] <msg>". Usefunctools.partialto create a functionlog_infowithlevelfixed to"INFO".
In the if __name__ == "__main__" block, demonstrate both tasks
with labeled output.
Expected output:
=== Accumulator (closure) ===
acc(10): 110
acc(20): 130
acc(5): 135
=== Partial: log_info ===
log_info("System started"): [INFO] System started
log_info("Sensor ready"): [INFO] Sensor ready
Deliverables
lecture5/closures_and_partials.pyThe program must run without errors and produce output matching the expected format above.
Exercise 4 – Data Processing Pipeline
Goal
Combine decorators, closures, partials, and higher-order functions to build a simple data processing pipeline for sensor readings.
Specification
Create a file lecture5/pipeline.py that implements the following.
Every function must have type hints and a Google-style docstring.
``log_call`` – A decorator that prints the function name when called. Use
@functools.wraps.``make_filter(threshold)`` – A closure that returns a function. The returned function takes a list of numbers and returns only those above the threshold.
``convert_temp`` – A function with the signature
convert_temp(value: float, from_scale: str, to_scale: str) -> floatthat converts between Celsius and Fahrenheit. Usefunctools.partialto createto_fahrenheit(from Celsius to Fahrenheit) andto_celsius(from Fahrenheit to Celsius).Pipeline – In the
if __name__ == "__main__"block:readings = [15.2, -3.0, 22.8, 8.1, -1.5, 30.0, 17.6]
Filter out negative readings using
make_filter(0).Convert each remaining reading to Fahrenheit using
to_fahrenheitwithmap.Sort the Fahrenheit results using
sorted()with a lambda key.Apply
@log_callto a function that orchestrates the pipeline.Print each stage’s output with labels.
Expected output (values should be computed dynamically):
=== Data Processing Pipeline ===
Calling: process_readings
Raw readings: [15.2, -3.0, 22.8, 8.1, -1.5, 30.0, 17.6]
After filtering (> 0): [15.2, 22.8, 8.1, 30.0, 17.6]
Converted to Fahrenheit: [59.36, 73.04, 46.58, 86.0, 63.68]
Sorted (ascending): [46.58, 59.36, 63.68, 73.04, 86.0]
Deliverables
lecture5/pipeline.pyThe program must run without errors and produce output matching the expected format above.
All calculations must be computed dynamically (no hard-coded results).
Every function must include type hints and a Google-style docstring.