Python · Functions

Complete Guide to Python Functions

A function is a named, reusable block of code that performs a specific task. Functions help you avoid repeating code, organize logic, and make programs easier to read and maintain.

1. What is a Function in Python?

A function is a block of code that runs only when it is called. You can pass data (arguments) into a function, and it can return data as a result.

Without a function:

print("Hello John")
print("Hello Maria")
print("Hello Alex")

With a function:

2. Defining a Function – def Keyword

Basic syntax: In Python, 'def' stands for definition and is used to create or define a function. When a programmer wants to create a new function, they use the def keyword followed by the function name. The function name should be descriptive and should convey the purpose of the function.

def function_name(parameters):
    # function body
    statement_1
    statement_2
    return some_value

Example:

If you don’t provide a return statement, the function returns None by default.

3. Calling a Function

Once defined, you call a function to execute the code inside it:

Values passed to the function are called arguments.

4. Parameters vs Arguments

Parameters are the variable names in the function definition. Arguments are the actual values you pass when calling the function.

def multiply(x, y):  # x, y are parameters
    return x * y

multiply(3, 4)      # 3, 4 are arguments

5. Types of Parameters

Python supports multiple kinds of parameters:

5.1 Positional Parameters

5.2 Default Parameters

Rule: default parameters must come after non-default parameters.

5.3 Keyword Arguments

With keyword arguments, the order doesn’t matter as long as you specify parameter names. Positional arguments must always come before keyword arguments.

5.4 *args – Variable Number of Positional Arguments

The term “variable number of arguments” in Python describes a function's capacity to take an arbitrary number of arguments. This is accomplished by using: *args : Allows the function to accept any number of positional arguments. These arguments are passed as a tuple to the function.

5.5 **kwargs – Variable Number of Keyword Arguments

In Python, **kwargs is a special syntax for defining functions that accept an undetermined number of keyword arguments. The kwargs argument captures any extra keyword arguments into a dictionary, where the keys are the argument names and the values are the actual arguments.

5.6 Combining *args and **kwargs

6. The return Statement

return sends a value back to the caller and ends the function.

6.1 Single Value

def square(x):
    return x * x

result = square(5)
print(result)  # 25

6.2 Multiple Values (Tuple Return)

In Python, you can return multiple values by simply separating them with commas in the return statement. In Python, comma-separated values are treated as tuples even without parentheses, unless parentheses are required by syntax

7. Functions Without returnNone

If a function does not explicitly return a value, Python automatically returns None.

8. Scope – Local vs Global Variables

The scope of a variable refers to the sections of a program where a variable is accessible. A local variable is only accessible in a defined section of the program, while a global variable is available for use in any section of the program.

8.1 Local Variables

8.2 Global Variables

8.3 Modifying Globals with global

9. Docstrings – Documenting Functions

A Python docstring is a string used to document a Python module, class, function or method, so programmers can understand what it does without having to read the details of the implementation. Also, it is a common practice to generate online (html) documentation automatically from docstrings.

def add(a, b):
    """
    Adds two numbers and returns the result.

    Parameters:
    a (int or float): first number
    b (int or float): second number
    """
    return a + b

print(add.__doc__)

Docstrings are used by tools like help() and IDEs for inline documentation.

10. Lambda Functions (Anonymous Functions)

Lambda functions in Python are powerful, concise tools for creating small, anonymous functions on the fly. They are perfect for simplifying short-term tasks, streamlining code with higher-order functions like map , filter , or sorted , and reducing clutter when defining temporary or throwaway logic.

Often used with map, filter, sorted:

11. First-Class Functions & Higher-Order Functions

In Python, functions are first-class objects: they can be stored in variables, passed as arguments, and returned from other functions. First-class functions let you treat functions like objects, giving you more flexibility in using them. Higher-order functions take this even further, allowing you to pass functions as arguments to other functions or return them as results.

11.1 Assigning Function to a Variable

11.2 Higher-Order Function

12. Nested Functions & Closures

When a function is defined within a function and the inner function accesses variables from the outer function, Python uses a "closure" to keep track of those variables that are defined just outside the inner function, in its enclosing scope.

The inner function inner remembers the value of message even after outer has finished. This is called a closure.

13. Recursion – Function Calling Itself

Python recursion is a technique where a function calls itself to solve a problem in a step-by-step manner. It is commonly used for solving problems that can be broken down into smaller subproblems, such as calculating factorials, Fibonacci sequences, and performing binary search.

Always define a base case in recursive functions to avoid infinite recursion (for example, if n == 1: above).

14. Generators (Functions with yield)

Generator functions are functions that have the yield keyword instead of return . These functions produce generator iterators, which are objects that represent a stream of data. The elements represented by an iterator are created and yielded only when required.

Generators produce values one at a time and are memory efficient because they don’t store the entire sequence at once.

15. Async Functions (Asynchronous)

Async keyword in Python is used to define asynchronous functions, which allow tasks to run without blocking the execution of other code. It is commonly used for handling tasks like network requests, database operations or file I/O, where waiting for one task to finish would normally slow down the entire program

import asyncio

async def say_hello():
    print("Hello...")
    await asyncio.sleep(1)
    print("World!")

asyncio.run(say_hello())

async def defines an asynchronous function and await suspends it until the awaited task is complete. This is useful for I/O-bound operations (network, disk, etc.).

16. Type Hints / Function Annotations

Type hints help you specify the expected types of parameters and return values. They don’t change runtime behavior but improve readability and tooling.

def add(a: int, b: int) -> int:
    return a + b

Type hints are a feature in Python that allow developers to annotate their code with expected types for variables and function arguments. This helps to improve code readability and provides an opportunity to catch errors before runtime using type checkers like mypy

17. Decorators – Functions That Wrap Functions

Python decorators allow you to modify or extend the behavior of functions and methods without changing their actual code. When you use a Python decorator, you wrap a function with another function, which takes the original function as an argument and returns its modified version.

The @log_call syntax is shorthand for: add = log_call(add). Decorators are powerful for adding cross-cutting behavior like logging, timing, authorization, etc.

18. Common Patterns Using Functions

Common patterns using functions in Python include functional programming techniques (like higher-order functions, recursion, closures, and decorators), design patterns (such as Singleton, Factory, Observer, and Strategy), and newer structural pattern matching with . These patterns make code more reusable, maintainable, and scalable.

18.1 Helper Functions

18.2 Utility Modules

# utils.py
def add(a, b):
    return a + b

def subtract(a, b):
    return a - b
# main.py
from utils import add, subtract

print(add(10, 5))
print(subtract(10, 5))

19. Real-World Example: Invoice Calculator

This example shows how multiple small functions can work together to build a real feature.

20. Summary

You have seen:

Functions are one of the most important concepts in Python. Mastering them will make all your future Python code cleaner, more modular, and easier to maintain.