Defining a function in Python is one of the most fundamental skills — it lets you encapsulate logic, avoid repetition, improve readability, and build modular, testable code. With the def keyword, you create reusable blocks that can take arguments, return values, and handle defaults, type hints, and more.
In 2026, modern Python functions use type hints (PEP 484/563/649), default parameters, *args/**kwargs, and clear docstrings. Here’s a complete, practical guide to defining, calling, and mastering functions.
1. Basic Function Definition & Call
def add_numbers(x: int, y: int) -> int:
"""Add two numbers and return the result."""
return x + y
# Call the function
result = add_numbers(3, 4)
print(result) # Output: 7
2. Default Arguments & Keyword Calls
def greet(name: str = "world", greeting: str = "Hello") -> str:
"""Return a personalized greeting."""
return f"{greeting}, {name}!"
print(greet()) # Hello, world!
print(greet("Alice")) # Hello, Alice!
print(greet(name="Bob", greeting="Hi")) # Hi, Bob!
3. Variable Arguments (*args, **kwargs)
def sum_all(*numbers: float) -> float:
"""Sum any number of numeric arguments."""
return sum(numbers)
print(sum_all(1, 2, 3)) # 6
print(sum_all(10, 20, 30, 40)) # 100
def print_info(**info: str | int) -> None:
"""Print key-value pairs (like a dict)."""
for key, value in info.items():
print(f"{key}: {value}")
print_info(name="Charlie", age=28, city="Denver")
# name: Charlie
# age: 28
# city: Denver
4. Combining All Features (Real-World Pattern)
def calculate_total(
items: list[float],
tax_rate: float = 0.08,
discount: float = 0.0,
*extra_fees: float,
**metadata: str
) -> float:
"""
Calculate total price with tax, discount, and extra fees.
Args:
items: List of item prices
tax_rate: Sales tax rate (default 8%)
discount: Discount percentage (default 0%)
*extra_fees: Variable extra charges
**metadata: Extra info (e.g., customer_id)
Returns:
Final total amount
"""
subtotal = sum(items)
subtotal += sum(extra_fees)
subtotal *= (1 - discount)
total = subtotal * (1 + tax_rate)
print(f"Metadata: {metadata}")
return round(total, 2)
# Examples
print(calculate_total([100, 50], discount=0.1)) # 148.50
print(calculate_total([200], 0.1, 0.05, 5.99, 2.50, customer_id="C123"))
# Metadata: {'customer_id': 'C123'}
# ? 219.49
5. Best Practices & Modern Python Tips (2026 Edition)
- Type hints — always use them (
: int,-> float) — improves readability and works with mypy/pylance - Docstrings — write clear ones (Google or NumPy style) — tools like Sphinx and IDEs use them
- Defaults — never use mutable defaults (
def func(lst=[])) — they persist across calls ? useNone+ check - *args/**kwargs — great for flexibility, but name them meaningfully (e.g.,
*extra_items) - Positional-only / keyword-only (Python 3.8+) — use
/and*in signature for clarity - Pitfall: modifying arguments inside function — avoid side effects unless intentional (pass copies if needed)
- Production tip: keep functions small (single responsibility), testable, and pure when possible
Conclusion
Defining functions with def is how you turn repeated code into reusable, readable, testable logic. In 2026, embrace type hints, clear docstrings, flexible arguments, and thoughtful defaults. Whether you're writing simple helpers or complex processing pipelines, good functions make your code cleaner, faster to debug, and easier to share. Master them, and you'll write Python that feels elegant and professional.
Next time you write the same logic twice — stop. Define a function instead. Your future self will thank you.