Previous | Tutorial index | Next
defdef keyword.Functions are the building blocks of reusable, organized, and readable code. They allow you to encapsulate logic, avoid repetition, and structure your programs into manageable pieces. In this tutorial, you will learn how to define your own functions in Python using the def keyword, how to pass data to them via parameters, how to return results, and how to call them effectively. We will also cover best practices like writing docstrings, understanding function scope, and the important distinction between pure and impure functions.
def Keyword – Function Definition SyntaxA function definition starts with the def keyword, followed by the function name, parentheses () containing optional parameters, a colon :, and an indented block of code.
def function_name(parameter1, parameter2):
"""Optional docstring."""
# function body
return result
def say_hello():
print("Hello, world!")
This function takes no arguments, does not return a value, and simply prints a message.
Python uses indentation to define blocks of code. All lines inside the function must be indented consistently (usually 4 spaces). Incorrect indentation will cause IndentationError.
def bad_indentation():
print("This is fine")
print("This will cause IndentationError") # different indentation level
calculate_average, get_user_input.save_data, process_order).def, return, class).A docstring is the first string literal that appears inside a function. It is used to describe what the function does, its parameters, and its return value. This is a critical part of writing maintainable code.
""" for multi‑line docstrings.help(function_name) and function_name.__doc__.def calculate_area(length, width):
"""
Calculate the area of a rectangle.
Args:
length (float): The length of the rectangle.
width (float): The width of the rectangle.
Returns:
float: The area (length * width).
"""
return length * width
help(calculate_area) # prints the docstring
This is a common source of confusion for beginners.
def square(number): # 'number' is a parameter
return number * number
result = square(5) # 5 is the argument
The order of arguments must match the order of parameters.
def introduce(name, age):
print(f"{name} is {age} years old.")
introduce("Alice", 30) # "Alice" -> name, 30 -> age
You can specify which argument corresponds to which parameter by name, allowing you to change the order.
introduce(age=25, name="Bob") # works fine
You can assign default values to parameters. If the caller omits an argument, the default is used.
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
print(greet("Alice")) # Hello, Alice!
print(greet("Bob", "Hi")) # Hi, Bob!
Important: Default parameters are evaluated once at definition time. Avoid using mutable defaults like
[]or{}unless you understand the implications (more on this later).
return StatementThe return statement exits the function and optionally passes back a value.
def add(a, b):
return a + b
sum_value = add(3, 4) # sum_value = 7
You can return multiple values by separating them with commas – Python packs them into a tuple.
def min_max(numbers):
return min(numbers), max(numbers)
low, high = min_max([1, 5, 3, 9]) # low=1, high=9
returnIf you do not include a return statement, or if you use return without a value, the function returns None.
def do_nothing():
pass
print(do_nothing()) # None
Python comes with many built‑in functions that are always available:
print(), len(), type(), int(), max(), min(), sorted(), sum(), range(), etc.Functions you define using def are stored in your module’s namespace and can be called just like built‑in functions.
# Custom function
def double(x):
return x * 2
# Calling both
print(double(5)) # 10
print(len("hello")) # 5
A pure function has two properties:
Example of a pure function:
def add(a, b):
return a + b
This is deterministic, predictable, and easy to test.
An impure function may rely on or modify state outside its scope, or it may produce side effects.
Examples:
counter = 0
def increment():
global counter
counter += 1 # modifies global state – impure
def log_message(msg):
print(msg) # side effect (printing) – impure
Guideline: Aim to write pure functions whenever possible. They are easier to reason about, test, and debug. However, real‑world programs inevitably need impure functions for I/O, logging, and state management. The key is to isolate impure parts from pure logic.
Variables defined inside a function are local – they exist only within that function.
def my_func():
x = 10 # local variable
print(x)
my_func()
# print(x) # NameError: name 'x' is not defined
Variables defined at the top level of a script are global. They can be read inside functions, but to modify them you need the global keyword.
y = 5 # global variable
def read_global():
print(y) # works fine
def modify_global():
global y
y = 99 # now modifies the global y
Best Practice: Minimize the use of global variables. Pass values as arguments instead of relying on globals.
*args – Variable‑Length Positional ArgumentsAllows a function to accept any number of positional arguments; they are collected into a tuple.
def sum_all(*numbers):
return sum(numbers)
print(sum_all(1, 2, 3)) # 6
print(sum_all(10, 20)) # 30
**kwargs – Variable‑Length Keyword ArgumentsAllows a function to accept any number of keyword arguments; they are collected into a dictionary.
def print_info(**info):
for key, value in info.items():
print(f"{key}: {value}")
print_info(name="Alice", age=30, city="NYC")
Danger: Using a mutable default (e.g., def append_to_list(item, lst=[]):) can lead to unexpected behavior because the default object is shared across calls.
def bad_append(item, lst=[]):
lst.append(item)
return lst
print(bad_append(1)) # [1]
print(bad_append(2)) # [1, 2] – unexpected!
Fix: Use None as a sentinel.
def good_append(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
Python 3.5+ supports type hints, which improve code clarity and can be used by static checkers like mypy.
def greet(name: str) -> str:
return f"Hello, {name}!"
They do not enforce types at runtime, but they make your intentions clear.
In Python, functions are objects. You can assign them to variables, pass them as arguments, and return them from other functions.
def square(x):
return x ** 2
func = square
print(func(5)) # 25
This is the foundation for higher‑order functions (e.g., map, filter, sorted with key).
Which keyword is used to define a function in Python?
functiondefdefinefuncWhat is a docstring?
What will be the output of this code?
def test(a, b=5):
return a + b
print(test(3))
385TypeErrorTrue or False: A function without a return statement implicitly returns 0.
What is the difference between a parameter and an argument?
Which of the following is a pure function?
def f(x): return x + 1def f(x): print(x); return xdef f(x): global y; y = x; return xdef f(x): open('file.txt', 'w').write(str(x))What does the global keyword do?
What will this code output?
def add(a, b):
return a + b
func = add
print(func(2, 3))
add(2, 3)52TypeErrorWhat is the issue with this function definition?
def append_to(item, lst=[]):
lst.append(item)
return lst
def line.lst must be a tuple.return before append.What does *args represent in a function definition?
Exercise 1: Basic Function
Write a function is_even(n) that takes an integer n and returns True if it is even, False otherwise. Test it with several numbers.
print(is_even(4)) # True print(is_even(7)) # False
</details>
**Exercise 2: Rectangle Geometry**
Define a function `rectangle_info(width, height)` that returns a tuple `(area, perimeter)`. Write a docstring for the function. Test with `width=5, height=3`.
<details><summary>Sample Solution</summary>
```python
def rectangle_info(width, height):
"""Return (area, perimeter) of a rectangle."""
area = width * height
perimeter = 2 * (width + height)
return area, perimeter
print(rectangle_info(5, 3)) # (15, 16)
Exercise 3: Greeting with Default
Write a function greet_user(name, greeting="Hello") that returns a formatted greeting. Call it with a name only, and then with a custom greeting.
print(greet_user("Alice")) # Hello, Alice! print(greet_user("Bob", "Hi")) # Hi, Bob!
</details>
**Exercise 4: Variable‑Length Sum**
Write a function `average(*numbers)` that returns the average of any number of numeric arguments. If no arguments are given, return `0.0`.
<details><summary>Sample Solution</summary>
```python
def average(*numbers):
if not numbers:
return 0.0
return sum(numbers) / len(numbers)
print(average(10, 20, 30)) # 20.0
print(average()) # 0.0
Exercise 5: Pure vs Impure
Rewrite the following impure function as a pure function:
total = 0
def add_to_total(amount):
global total
total += amount
return total
Then, write a pure version that takes the current total as an argument and returns the new total.
new_total = add_to_total(10, 5) # returns 15
</details>
---
### 🏠 Homework – Deeper Thinking
#### Short Answer Questions
**1. Temperature Converter**
Write a function `convert_temp(value, from_unit, to_unit)` that converts between Celsius, Fahrenheit, and Kelvin. Return the converted value rounded to 2 decimal places. Raise `ValueError` for invalid units.
<details><summary>Sample Answer</summary>
```python
def convert_temp(value, from_unit, to_unit):
# Convert from_unit to Celsius first
if from_unit == 'C':
celsius = value
elif from_unit == 'F':
celsius = (value - 32) * 5 / 9
elif from_unit == 'K':
celsius = value - 273.15
else:
raise ValueError("Invalid from_unit")
# Convert Celsius to target
if to_unit == 'C':
result = celsius
elif to_unit == 'F':
result = celsius * 9 / 5 + 32
elif to_unit == 'K':
result = celsius + 273.15
else:
raise ValueError("Invalid to_unit")
return round(result, 2)
2. Password Validator
Write a function validate_password(password) that checks length, uppercase/lowercase/digit presence, and absence of substring 'password'. Return a tuple (bool, list_of_failures).
3. Fibonacci with Memoization
Write a pure function fibonacci(n) using a default cache dictionary for memoization.
4. Shopping Cart Functions
Design a set of functions to manage a shopping cart represented as a list of dictionaries. Write add_item, remove_item, total_price, and checkout functions. Decide whether they are pure or impure and document clearly.
def remove_item(cart, item): """Impure: removes first matching item.""" for i, entry in enumerate(cart): if entry['item'] == item: del cart[i] return
def total_price(cart): """Pure: returns total without modifying cart.""" return sum(entry['price'] * entry['quantity'] for entry in cart)
def checkout(cart): """Impure: prints receipt and clears cart.""" print("Receipt:") for entry in cart: print(f"{entry['item']} x{entry['quantity']} = ${entry['price']*entry['quantity']:.2f}") cart.clear()
</details>
**5. Function Composition**
Write a function `compose(f, g)` that returns a new function `h` such that `h(x) = f(g(x))`. Then write a `chain` function that composes any number of functions in order.
<details><summary>Sample Answer</summary>
```python
def compose(f, g):
return lambda x: f(g(x))
def chain(*funcs):
def result(x):
for f in funcs:
x = f(x)
return x
return result
# Example
def square(x): return x * x
def double(x): return x * 2
h = compose(square, double) # square(double(x))
print(h(3)) # 36
c = chain(square, double) # double(square(x))
print(c(3)) # 18
if/elif to convert to a base unit (Celsius) first, then convert to the target. Raise ValueError for invalid units.'password' in password.lower().cache dictionary persists and stores computed values. Use if n in cache: return cache[n].add_item, loop to find existing item. Use sum(item['price'] * item['quantity'] for item in cart).def compose(f, g): return lambda x: f(g(x)). For chain, start with identity function or use functools.reduce.In this tutorial, you have learned:
def keyword, with proper indentation.None).global keyword.*args, **kwargs) and the mutable default pitfall.Functions are the primary mechanism for code reuse and abstraction in Python. Mastering them is essential for writing clean, efficient, and maintainable programs.
Next Steps: In Tutorial 3, we will explore Control Flow – conditionals and loops – and see how to combine them with functions to solve more complex problems.
Happy coding!