Chapter 6 Functions
In Python, return and print are used for different purposes in functions:
return:returnis used to send a value back to the caller of the function.- When a function is called, it can perform some operations and then use
returnto send a result back to where the function was called. - The value returned by
returncan be stored in a variable, used in expressions, or passed to other functions. - Once
returnis executed, the function terminates immediately.
Example:
print:printis used to output text to the console.- It does not send any value back to the caller; it simply outputs the given string or other data types to the standard output (usually the console).
- The function continues executing after
printunless it encounters areturnor another statement that terminates the function.
Example:
6.0.1 Summary
- Use
returnto send a value from the function to its caller. - Use
printto display a value to the console.
Here is a combined example to illustrate both:
def get_and_display_greeting():
greeting = "Hello, World!"
print(greeting) # This will print: Hello, World!
return greeting
returned_value = get_and_display_greeting()
print(f"The returned value is: {returned_value}") # This will print: The returned value is: Hello, World!In this example, print outputs the greeting to the console, and return sends the greeting back to where the function was called, which is then stored in returned_value and printed again.
Note:Functions that do not have an explicit return expression will implicitly return the None object. The details of None will be covered in a later exercise. For the purposes of this exercise and explanation, None is a placeholder that represents nothing, or null:
6.1 Parameters and arguments
Parameters are names in a function definition; arguments are the values passed by the caller. Put required parameters first and use defaults only when one behavior is genuinely appropriate for most calls.
def calculate_total(price, quantity, discount_rate=0.0):
"""Calculate an order total after a proportional discount."""
if quantity < 0:
raise ValueError("quantity must be nonnegative")
if not 0 <= discount_rate <= 1:
raise ValueError("discount_rate must be between 0 and 1")
subtotal = price * quantity
return subtotal * (1 - discount_rate)
assert calculate_total(10, 3) == 30
assert calculate_total(10, 3, discount_rate=0.10) == 27Keyword arguments make calls with several similar values easier to review.
Avoid mutable defaults such as items=[], because the same object is reused
across calls.
6.2 Variable-length arguments
Use *args for additional positional arguments and **kwargs for additional
keyword arguments when the function truly supports an open-ended interface.
An explicit signature is clearer when the accepted inputs are known.
6.3 Scope and side effects
Names assigned inside a function are local unless declared otherwise. Prefer returning a result over mutating global state; functions with explicit inputs and outputs are easier to test and reuse.
tax_rate = 0.08
def add_tax(amount, rate):
total = amount * (1 + rate)
return total
assert add_tax(100, tax_rate) == 108The function reads no hidden global configuration because the rate is passed
explicitly. A local variable such as total disappears after the call.
6.4 Lambda expressions
A lambda is a small anonymous function limited to one expression. It is useful
for short local operations such as a sort key. Use def when logic needs a
name, validation, documentation, or multiple steps.
6.5 Function interview checklist
- Are inputs, outputs, and failure behavior explicit?
- Is a mutable default accidentally shared across calls?
- Does the function rely on hidden global state?
- Is it doing one coherent job?
- Would a named function be clearer than a lambda?
- Can representative and edge cases be tested with simple assertions?