Practice: Functions¶
View practice code on GitHub Get the Video Course
From the lesson
Practice problems for Section 07 Concepts. Build each yourself first, then expand the solution to check.
Twelve practice problems, one per concept step. The numbers line up (Practice-01 goes with Step-01). Build each one yourself in python-practice, then compare with python-practice/solutions. Do this before starting the next section.
Write the code yourself. The stubs only describe the task. Two problems end with a short "Write a Program" exercise that uses input().
These problems build one connected story: you are writing the helper functions for an online store (order totals, receipt lines, discounts, price formatting). Each step adds another small helper to that toolkit.
Step-01: Define and Call a Function¶
Concepts: def with no parameters, calling a function with (), calling the same function many times, docstrings, reading a docstring with __doc__, define once and call many times (reuse, no copy-paste).
Problem-1: Define and Call
Write a function print_welcome that takes no arguments and prints Welcome to the Online Store!, then call it two times.
Need a hint?
Define print_welcome with def print_welcome(): and no parameters, put print(...) on an indented line inside, then write print_welcome() twice (the () is what runs it).
Show the solution
Problem-2: A Docstring
Write a function store_tagline that takes no arguments, carries the docstring Print the store tagline., and prints Great prices, fast delivery.. Then:
- Task-1: call
store_tagline. - Task-2: print
store_tagline's own docstring (read it from the function's__doc__attribute).
Need a hint?
The docstring is a string literal as the FIRST line inside the function body; read it later with store_tagline.__doc__, which is separate from what the function prints.
Show the solution
Problem-3: Define Once, Call Many
Write a function print_divider that takes no arguments and prints ==============, then call it, print Today's Deals, and call it again.
Need a hint?
Define print_divider once, then call it as many times as you like; that is reuse, no copy-paste of the print(...).
Show the solution
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-02: One Argument¶
Concepts: parameters vs arguments, passing a value as an argument, passing a variable as an argument, positional arguments fill parameters left to right (first value goes to first parameter), input().
Problem-1: Greet a Customer
Write a function greet_customer that takes a customer and prints Hello, <customer>!. Call it with Ben, then with Joe, then store Zoe in a variable shopper and call it with that variable.
Need a hint?
Give greet_customer a customer parameter and build the message with an f-string like f"Hello, {customer}!"; an argument can be a literal ("Kalyan") or a variable (shopper).
Show the solution
Problem-2: Positional Arguments
Write a function label_product that takes a product and a section and prints <product> is in <section>. Call it with Mouse and Audio in that order (so the first value fills product and the second fills section), then call it again with Cable and Video.
Need a hint?
With positional arguments the first value fills the first parameter: label_product("Mouse", "Audio") sets product then section, by order alone.
Show the solution
Problem-3 (Write a Program): Greet Any Shopper
Write a program that asks the user for a shopper name, then calls greet_customer with what they typed.
Need a hint?
Read the name with input("Shopper name: ") and pass that variable straight into the function you already wrote - no need for a second function.
Show the solution
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-03: Return (print vs return)¶
Concepts: return a value from a function so it can be stored in a variable and reused, the difference between print and return (a function that only prints hands back None), returning the result of a comparison to answer a yes/no question (a bool).
Problem-1: Return and Reuse
Write a function order_total that takes a price and a quantity and returns their product. Call it with 2 and 3, store the result in total_due, print total_due, then print total_due multiplied by 10.
Need a hint?
return price * quantity hands the value back so you can store it in total_due and reuse it, unlike print which only shows it.
Show the solution
Problem-2: Print vs Return
Write a function print_receipt_line that takes a price and a quantity and only PRINTS their product (it has no return, so it hands back None). Call it with 75 and 4, store what it hands back in handed_back, and print handed_back.
Need a hint?
A function with no return hands back None; capturing print_receipt_line(...) in handed_back and printing it shows None even though the product was printed.
Show the solution
Problem-3: A Yes or No Answer
Write a function in_budget that takes an amount and returns whether amount is 100 or less (a True/False answer). Call it with 90 and print the result, then call it with 150 and print the result.
Need a hint?
amount <= 100 already evaluates to a bool, so return amount <= 100 returns True or False directly, no if needed.
Show the solution
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-04: Parameters and Logic¶
Concepts: a function with more than one parameter (arguments fill parameters by position), if/elif/else logic inside a function, a loop inside a function that keeps a running total and returns the built-up result, input().
Problem-1: Many Parameters (Shipping Fee)
Write a function shipping_fee that takes a weight and a rate and returns their product. Call it with 4 and 3 and print the result, then call it with 10 and 2 and print the result.
Need a hint?
Two parameters fill by position: shipping_fee(4, 3) gives weight=4, rate=3, and return weight * rate.
Show the solution
Problem-2: Logic Inside a Function (Discount Tier)
Write a function discount_tier that takes a spend and returns a tier label: A for 90 or more, B for 75 or more, C for 50 or more, otherwise F. Call it with 95, with 80, and with 40, printing each result.
Need a hint?
Chain if/elif/else from the highest threshold down; the first matching branch returns, so order matters.
Show the solution
Problem-3: Loop Inside a Function (Cart Sum)
Write a function cart_sum that takes a list line_prices and returns the total of its items by adding them up in a loop. Call it with [15, 25, 35] and print the result, then call it with [5, 5, 5, 5] and print the result.
Need a hint?
Start a running total at 0 before the loop, add each item with running = running + price, then return running after the loop.
Show the solution
Problem-4: Stop at the First Match (Over Budget)
Write a function any_over_budget that takes a list prices and a limit and returns True the moment it finds the first price above limit (return right there, do not keep checking), otherwise returns False after the loop. Call it with [20, 45, 90] and 50 and print the result, then call it with [20, 30, 40] and 50 and print the result.
Need a hint?
Loop the prices and return True the moment one is above limit; put return False AFTER the loop so it only fires once every price has been checked.
Show the solution
# Problem-4: return True on the first price above the limit, else False
def any_over_budget(prices, limit):
for price in prices:
if price > limit:
return True # found one, so stop right here
return False # only reached after checking every price
print(any_over_budget([20, 45, 90], 50))
print(any_over_budget([20, 30, 40], 50))
Problem-5 (Write a Program): Shipping for Any Order
Write a program that asks the user for a weight and a rate (both whole numbers), calls shipping_fee with them, and prints Shipping: followed by the fee.
Need a hint?
Wrap each input() in int() so you get numbers, not text, then reuse shipping_fee(weight, rate) and print the result with a Shipping: label.
Show the solution
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-05: Default Parameters and Keyword Arguments¶
Concepts: default parameter values, calling with and without the optional argument, keyword arguments (name=value in the call so order does not matter), the mutable-default trap (use None, not []).
Problem-1: A Default Currency
Write a function format_price that takes an amount and a currency that defaults to USD, and prints <amount> <currency>. Call it with 25 only (using the default currency), then call it with 30 and EUR (overriding the currency).
Need a hint?
A default like currency="USD" makes the argument optional; pass only amount to use the default, or pass a second value to override it.
Show the solution
Problem-2: Keyword Arguments
Write a function stock_note that takes a product and a section and prints <product> is stocked in <section>. Call it passing the arguments BY NAME and out of order, section before product, using Mouse and Audio.
Need a hint?
Keyword arguments (stock_note(section="Audio", product="Mouse")) bind by name, so order does not matter.
Show the solution
Problem-3: The Mutable-Default Trap
Write a function add_to_cart that takes an item and a cart that defaults to None, starts a fresh empty list when cart is None, adds item to the cart, and returns the cart. Call it with mouse and print the result, then call it with keyboard and print the result (each call must start with a fresh list).
Never use [] as a default value
A default like cart=[] is created once and shared across every call, so items pile up between calls. Use cart=None and create a fresh list inside the function instead.
Need a hint?
Use cart=None and create a fresh [] inside when it is None; a cart=[] default would be shared across calls and accumulate items.
Show the solution
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-06: Return Many Values¶
Concepts: returning several values comma-separated (a tuple), tuple unpacking, min()/max(), .split(), indexing [0] and [-1], f-strings.
Problem-1: Cheapest and Dearest
Write a function price_range that takes a list prices and returns two values, the lowest and the highest. Then, for the list [40, 95, 25, 70]:
- Task-1: call
price_range, store the single returned value, and print it (you will see a tuple). - Task-2: call
price_rangeagain, unpack the two returned values intolowandhighin one line, and printlow: 25andhigh: 95.
Need a hint?
return min(prices), max(prices) returns a tuple; print it whole to see (25, 95), or unpack with low, high = price_range(...) to name the two values.
Show the solution
def price_range(prices):
return min(prices), max(prices)
# Problem-1 Task-1: store and print the returned tuple
spread = price_range([40, 95, 25, 70])
print(spread)
# Problem-1 Task-2: unpack the two returned values
low, high = price_range([40, 95, 25, 70])
print("low:", low)
print("high:", high)
Problem-2: Split a Product Code
Write a function split_code that takes a product_code and returns two values, the first part and the last part (split on -). Call it with TEC-2024-15, unpack the two returned values into prefix and suffix, and print prefix = TEC and suffix = 15.
Need a hint?
.split("-") makes a list of parts; parts[0] is the first and parts[-1] is the last, and returning both comma-separated gives a tuple to unpack into prefix, suffix.
Show the solution
Problem-3: Three Price Stats
Write a function price_stats that takes a list prices and returns three values, the lowest, the highest, and how many prices there are. Call it with [40, 95, 25, 70], unpack the three returned values into low, high, and count in one line, and print low: 25, high: 95, and count: 4.
Need a hint?
return min(prices), max(prices), len(prices) hands back three values comma-separated; unpack all three at once with low, high, count = price_stats(...).
Show the solution
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-07: args and *kwargs¶
Concepts: *args gathers positional values into a tuple (sum()), call-site unpacking of a list with *, **kwargs gathers named values into a dict (iterating items()), call-site unpacking of a dict with **, keyword-only parameters (a bare *).
Problem-1: gather positional args and unpack a list
Write a function sum_prices that gathers any number of positional arguments (use *amounts) and returns their sum. Then:
- Task-1: call
sum_priceswith4, 5, 6and print the result. - Task-2: call
sum_priceswith25, 35, 45, 55and print the result. - Task-3: define a list
line_itemsholding8, 12, 20, callsum_priceswith that list unpacked into the call (use*line_items), and print the result.
Need a hint?
*amounts in the definition gathers positional arguments into a tuple; *line_items at the call site spreads a list back out into separate arguments.
Show the solution
def sum_prices(*amounts):
return sum(amounts)
# Problem-1 Task-1: call with 1, 2, 3
print(sum_prices(4, 5, 6))
# Problem-1 Task-2: call with 10, 20, 30, 40
print(sum_prices(25, 35, 45, 55))
# Problem-1 Task-3: unpack a list into the call
line_items = [8, 12, 20]
print(sum_prices(*line_items))
Problem-2: gather named args and unpack a dict
Write a function print_order that gathers any number of named arguments (use **fields) and prints each key: value pair on its own line. Then:
- Task-1: call
print_orderwith the named argumentsproduct="Mouse"andprice=25. - Task-2: define a dict
order_fieldsmappingproducttoKeyboardandpriceto45, then callprint_orderwith that dict unpacked into the call (use**order_fields).
Need a hint?
**fields gathers named arguments into a dict; loop fields.items() for key/value, and **order_fields at the call site spreads a dict into named arguments.
Show the solution
def print_order(**fields):
for key, value in fields.items():
print(f"{key}: {value}")
# Problem-2 Task-1: call with named arguments
print_order(product="Mouse", price=25)
# Problem-2 Task-2: unpack a dict into the call
order_fields = {"product": "Keyboard", "price": 45}
print_order(**order_fields)
Problem-3: keyword-only arguments with a bare *
Write a function pack_size that takes keyword-only parameters length and width (a bare * before them forces callers to pass them by name) and returns their product. Call it with length=3 and width=4 and print the result.
Need a hint?
A bare * before length and width makes them keyword-only, so they must be passed as pack_size(length=3, width=4).
Show the solution
Problem-4: one function with both *args and **kwargs
Write a function place_order that gathers any number of positional arguments into *items and any number of named arguments into **options (the *items must come BEFORE **options), and prints items: followed by the items tuple on one line, then options: followed by the options dict on the next line. Call it with the positional arguments mouse and cable and the named arguments express=True and note="Gift".
Need a hint?
One function can take both: write def place_order(*items, **options) with *items BEFORE **options; the positional arguments land in the items tuple and the named ones in the options dict.
Show the solution
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-08: Scope (LEGB)¶
Concepts: local scope, reading vs shadowing a global name, the global statement (a function changing a global variable), enclosing scope (nested functions), the nonlocal statement.
Problem-1: Local and global
Define a global variable status set to open, then write a function set_status that takes no arguments, sets its OWN local status to closed, and prints it. Call set_status, then print the global status to show it did not change.
Need a hint?
Assigning status inside set_status creates a new LOCAL name; the global status is untouched, so it still prints "open" afterward.
Show the solution
Problem-2: The global statement
Define a global variable cart_count set to 0, then write a function add_item that takes no arguments, declares cart_count with the global statement, and increases cart_count by 10. Call add_item twice, then print cart_count.
Without global, an assignment makes a new local
Inside add_item, assigning to cart_count would create a brand-new local variable and leave the global cart_count untouched, unless you first declare global cart_count.
Need a hint?
global cart_count tells Python the assignment targets the module-level cart_count, so the two += 10 calls accumulate to 20.
Show the solution
Problem-3: Enclosing scope and nonlocal
Write a function make_register that starts a local variable tally at 0 and holds a nested function ring_up which declares tally with nonlocal, increases it by 1, and returns it; inside make_register, call ring_up twice and print each result. Then call make_register.
Need a hint?
nonlocal tally lets the nested ring_up rebind the tally in the enclosing make_register, so the count persists across the two calls.
Show the solution
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-09: First-class and Higher-order Functions¶
Concepts: a function is a value (store it in a variable, no parentheses, and call it through the new name), higher-order functions (pass a function name as an argument and call it inside another function), calling the passed-in function on its own result.
Problem-1: Store a function in a variable
Write a function triple_price that takes n and returns it multiplied by 3, store the function itself in a variable named bulk_price (the name with no parentheses), then call bulk_price with 5 and with 20, printing each result.
Store the function, do not call it
Write bulk_price = triple_price with no parentheses to store the function itself. Writing bulk_price = triple_price(5) would call triple_price and store its result, not the function.
Need a hint?
bulk_price = triple_price (no parentheses) stores the function itself; bulk_price(5) then calls it. Writing triple_price(5) would store the result instead.
Show the solution
Problem-2: Pass a function as an argument
Write a function apply_to that takes a function func and a value and returns the result of calling func on value, plus a function markup that returns a number multiplied by itself and a function markdown that returns a number's negative. Call apply_to with markup and 6 and print the result, then call apply_to with markdown and 6 and print the result.
Need a hint?
apply_to(func, value) is higher-order: it calls func(value) inside, so passing markup or markdown by name picks which function runs.
Show the solution
Problem-3: Apply a function twice
Write a function apply_again that takes a function func and a value and returns the result of applying func to value twice (call func on value, then call func on that result), plus a function add_fee that returns a number plus 1. Call apply_again with add_fee and 10 and print the result.
Need a hint?
apply_again feeds the first result back in: func(func(value)), so add_fee applied twice to 10 gives 12.
Show the solution
Problem-4: map and filter Over a Price List
Write a function add_tax that takes n and returns it plus 10 percent of it, worked out with whole-number division so the answer stays an int, and a function is_pricey that takes n and returns whether n is above 100 (a True/False answer). Define a variable prices as a list with the values 60, 140, 80, 210. Then:
- Task-1: use
mapto applyadd_taxto every price inprices, turn the result into a list, and print it. - Task-2: use
filterto keep only the prices thatis_priceysays are pricey, turn the result into a list, and print it.
Need a hint?
map(add_tax, prices) applies add_tax to every price and filter(is_pricey, prices) keeps only the ones is_pricey returns True for; wrap each in list(...) to see the result.
Show the solution
# Problem-4: map applies a function to every item, filter keeps the ones that pass a test
def add_tax(n):
return n + n // 10
def is_pricey(n):
return n > 100
prices = [60, 140, 80, 210]
print(list(map(add_tax, prices))) # apply add_tax to each price
print(list(filter(is_pricey, prices))) # keep only the pricey ones
Problem-5: Pick a Function From a Dict (Dispatch)
Write a function add_fee that takes n and returns it plus 5, and a function add_tax that takes n and returns it plus 10 percent of it, worked out with whole-number division so the answer stays an int. Put both functions in a dict named charges under the keys fee and tax (store the function names, no parentheses). Then look up the function under the key tax, store it in a variable named chosen, call chosen with 200, and print the result. Then look up the function under the key fee, call it with 200, and print the result.
Need a hint?
Store the functions in charges = {"fee": add_fee, "tax": add_tax} with no parentheses, then pick one by key: charges["tax"] gives the function back so you can call it with chosen(200).
Show the solution
# Problem-5: functions live in a dict and are picked by key (dispatch)
def add_fee(n):
return n + 5
def add_tax(n):
return n + n // 10
charges = {"fee": add_fee, "tax": add_tax} # store the functions, no parentheses
chosen = charges["tax"] # look up the function by key
print(chosen(200)) # then call it
print(charges["fee"](200)) # look up and call in one step
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-10: Lambda¶
Concepts: lambda, a one-line ANONYMOUS function (lambda args: expression) built and called on the spot, passing a lambda as key= to sorted() and to max(), len(), tuple indexing (pair[1]).
Problem-1: A One-Line Function
A lambda has no name, so to name a function you use def. Build a one-line lambda that takes n and gives back n multiplied by 2, and call it directly with 7 and then with 10, printing each result. Do not store the lambda in a variable.
Need a hint?
A lambda has no name - wrap it in parentheses and call it on the spot: (lambda n: n * 2)(7). To NAME a function you would use def.
Show the solution
Problem-2: Sort Products by Name Length
For the list of product names pear, fig, banana, kiwi, print the names sorted from shortest to longest, using sorted() with a lambda as the key=.
Need a hint?
Pass key=lambda name: len(name) to sorted() so it orders the product names by length instead of alphabetically.
Show the solution
Problem-3: Sort Products by Price, and Find the Dearest
- Task-1: For the list of (product, price) pairs
("Monitor", 200),("Mouse", 80),("Keyboard", 95), print the pairs sorted by price (the second item of each pair), usingsorted()with alambdaas thekey=. - Task-2: Print the single most expensive pair, using
max()with the samelambdaas thekey=.
Need a hint?
Task-1: key=lambda pair: pair[1] sorts each (product, price) pair by its second item, the price. Task-2: max() takes the same key=, so it returns the whole pair with the highest price.
Show the solution
# Problem-3 Task-1: sort pairs by price with a lambda key
priced_items = [("Monitor", 200), ("Mouse", 80), ("Keyboard", 95)]
print(sorted(priced_items, key=lambda pair: pair[1]))
# Problem-3 Task-2: the dearest pair, same lambda as the key
print(max(priced_items, key=lambda pair: pair[1]))
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-11: Modules and Imports¶
Concepts: import a standard-library module and call module.function() (math.sqrt, math.floor), from module import name1, name2 (pi, ceil), write a .py module of functions and import from your OWN module, and shorten a module or a name with as.
Problem-1: Use the math module
Import the math module, then:
- Task-1: apply
math.sqrtto81and print the result. - Task-2: apply
math.floorto9.8and print the result.
Need a hint?
import math then reach members with dot access: math.sqrt(81) and math.floor(9.8).
Show the solution
Problem-2: from math import name
From the math module, import the names pi and ceil, then:
- Task-1: print
pi. - Task-2: apply
ceilto7.2and print the result.
Need a hint?
from math import pi, ceil pulls those names in directly, so you write pi and ceil(7.2) without the math. prefix.
Show the solution
Problem-3: Import from your OWN module
- Task-1: create
s07_practice11_pricetools.pynext to this file holding atagfunction (takes a product name, returns it in capitals with!added) and awith_taxfunction (takes a price, returns the price with 10 percent tax added, rounded to 2 decimals). - Task-2: in THIS file, import both
tagandwith_taxfrom that module, then calltagwithwelcomeand print the result and callwith_taxwith100and print the result.
Need a hint?
Put tag and with_tax in s07_practice11_pricetools.py, then from s07_practice11_pricetools import tag, with_tax here
Show the solution
Problem-4: Give a module and a name a short alias with as
- Task-1: import the
mathmodule under the short aliasm, then applym.sqrtto49and print the result. - Task-2: from the
mathmodule, import the namefactorialunder the aliasfact, then applyfactto5and print the result.
Need a hint?
import math as m gives the module a short handle, so you call m.sqrt(49); from math import factorial as fact renames a single imported name, so you call fact(5).
Show the solution
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-12: Recursion (bonus)¶
Concepts: recursion (a function that calls itself), a base case to stop, a recursive call with a smaller value.
Problem-1: shelf countdown
Write a recursive function shelf_countdown that takes n: when n is 0 it prints All shelves stocked! and stops (the base case), otherwise it prints n and counts down from one less. Call it with 3.
Need a hint?
The base case if n == 0 prints "All shelves stocked!" and returns to stop; otherwise shelf_countdown(n - 1) recurses toward 0.
Show the solution
Problem-2: running product
Write a recursive function running_product that takes n: when n is 1 it returns 1 (the base case), otherwise it returns n multiplied by the running product of one less. Call it with 4 and print the result, then call it with 6 and print the result.
Need a hint?
Base case if n == 1: return 1; otherwise return n * running_product(n - 1) multiplies down to the base case.
Show the solution
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Finished this section?
Check your work against the solutions above, then head back to the Section 07 lesson, or try the Section 07 workshop for more reps.
Prefer to learn by watching?
The full video course teaches every concept on screen and builds the projects with you, step by step.
Practice: Loops and Comprehensions Next: Practice: Type Hints