Functions - Creating Your Own Commands
Functions are like kitchen appliances. A blender (function) takes ingredients (inputs), processes them, and gives you a smoothie (output). You don't need to know how the blender works inside - just what goes in and what comes out.
A **function** is a reusable block of code that performs a specific task. Instead of writing the same code multiple times, you define a function once and then call it whenever you need that behavior. This makes your programs shorter, more organized, and easier to debug.
**Defining a function:**
Use the `def` keyword, followed by the function name, parentheses `()`, and a colon `:`.
```python
def function_name():
# code block
```
The function name should be descriptive (verb or verb phrase) and follow the same naming rules as variables (lowercase with underscores).
**Calling a function:**
Write the function name followed by parentheses:
```python
function_name()
```
**Parameters and arguments:**
- **Parameters** are variables listed in the function definition. They act as placeholders for the values the function will receive.
- **Arguments** are the actual values you pass to the function when calling it.
```python
def greet(name): # 'name' is a parameter
print(f"Hello {name}")
greet("Alice") # 'Alice' is an argument
```
**Return values:**
Use the `return` statement to send a value back to the caller. If no `return` is used, the function returns `None`.
```python
def add(a, b):
return a + b
result = add(5, 3) # result becomes 8
```
**Default parameter values:**
You can provide default values for parameters. If the caller doesn't supply an argument, the default is used.
```python
def greet(name="Guest"):
print(f"Hello {name}")
greet() # Hello Guest
greet("Sam") # Hello Sam
```
**Keyword arguments:**
When calling a function, you can specify arguments by parameter name, which allows you to pass them in any order:
```python
def describe_person(name, age, city):
print(f"{name} is {age} and lives in {city}")
describe_person(age=25, city="New York", name="John")
```
**Variable scope:**
- Variables defined inside a function are **local** – they only exist inside that function.
- Variables defined outside any function are **global** – they can be accessed anywhere (but modifying them inside a function requires the `global` keyword).
**Docstrings (documentation):**
A docstring is a string literal right after the function definition that explains what the function does. It's enclosed in triple quotes `"""`.
```python
def multiply(a, b):
"""Return the product of a and b."""
return a * b
```
You can view a function's docstring with `help(multiply)`.
**Why use functions?**
1. **Reusability** – write once, use many times.
2. **Modularity** – break complex problems into smaller, manageable pieces.
3. **Abstraction** – hide complex implementation details.
4. **Testing** – easier to test individual functions.
5. **Collaboration** – different developers can work on different functions.
**Common mistakes:**
- Forgetting the colon `:` after the function definition.
- Indentation errors – all code inside the function must be indented.
- Using a variable name that shadows a built‑in function (e.g., `def print():`).
- Forgetting to return a value when needed (returns `None` by default).
- Modifying a global variable without declaring `global` inside the function.
**Practice exercises:**
1. Write a function `is_even(n)` that returns `True` if `n` is even, `False` otherwise.
2. Write a function `factorial(n)` that returns the factorial of `n` (e.g., `5! = 120`).
3. Write a function `greet_user(first_name, last_name)` that returns a full greeting.
4. Write a function `max_of_three(a, b, c)` that returns the largest number.
5. Write a function `count_vowels(text)` that returns the number of vowels in a string.
**Real‑world applications:**
- Mathematical calculations (e.g., `calculate_tax(amount, rate)`)
- Data validation (e.g., `is_valid_email(email)`)
- File processing (e.g., `read_csv(filename)`)
- API wrappers (e.g., `get_weather(city)`)
- Game logic (e.g., `calculate_damage(attack, defense)`)
**Example with multiple return values:**
Functions can return multiple values as a tuple:
```python
def get_min_max(numbers):
return min(numbers), max(numbers)
smallest, largest = get_min_max([5, 2, 8, 1, 9])
```
# ========== EXAMPLE 1: Basic Function (No Parameters, No Return) ==========
print("=== Example 1: Simple Greeting Function ===")
def say_hello():
"""This function prints a welcome message"""
print("Hello!")
print("Welcome to Python!")
print("Calling function first time:")
say_hello()
print("\nCalling function second time:")
say_hello()
print()
# ========== EXAMPLE 2: Function with Parameters and Return Value ==========
print("=== Example 2: Area Calculator and Temperature Converter ===")
def calculate_area(length, width):
"""Calculate area of a rectangle"""
area = length * width
return area
room_area = calculate_area(10, 12)
print(f"Room area: {room_area} square feet")
def celsius_to_fahrenheit(celsius):
"""Convert Celsius to Fahrenheit"""
return (celsius * 9/5) + 32
temp_c = 25
temp_f = celsius_to_fahrenheit(temp_c)
print(f"{temp_c}°C = {temp_f}°F")
print()
# ========== EXAMPLE 3: Default Parameters and Keyword Arguments ==========
print("=== Example 3: Default Values and Keyword Arguments ===")
def order_coffee(flavor="regular", size="medium"):
"""Order a coffee with optional flavor and size"""
print(f"One {size} {flavor} coffee coming up!")
# Using default parameters
order_coffee() # both defaults
order_coffee("cappuccino") # override flavor, size default
order_coffee(size="large") # keyword argument
order_coffee(flavor="vanilla", size="small") # both keyword arguments
# Function with multiple return values
def get_stats(numbers):
"""Return min and max of a list as a tuple"""
return min(numbers), max(numbers)
scores = [85, 92, 78, 90, 88]
lowest, highest = get_stats(scores)
print(f"\nScores: {scores}")
print(f"Lowest: {lowest}, Highest: {highest}")
→ Run this code interactively