Functions and Recursion in Python

In Python, functions are reusable blocks of code designed to perform a specific task. They help in breaking down large programs into smaller, manageable, and organized parts.

A function can accept inputs (parameters), perform operations, and return an output (return value).

Defining Functions

Functions in Python are defined using the def keyword, followed by the function name, parameters (if any), and a block of code.

Syntax:
def function_name(parameters):
    # function body
    # statements
    return value
Example:
def greet():
    print("Hello, welcome to Python!")
Calling the function:
greet()
Output:
Hello, welcome to Python!

Parameters and Arguments

Parameters are variables defined inside the function parentheses, while arguments are the actual values passed when calling the function.
Example:
def add(a, b):
    return a + b

result = add(10, 5)
print(result)  # Output: 15
Here, a and b are parameters, while 10 and 5 are arguments.

Return Statement

A return statement sends the result back to the caller. If no return statement is used, the function returns None by default.
Example:
def square(n):
    return n * n

print(square(6))  # Output: 36

Default Arguments

You can assign default values to parameters. If no argument is passed for such parameters, the default value is used.
Example:
def greet(name="Guest"):
    print("Hello,", name)

greet("Alice")   # Output: Hello, Alice
greet()          # Output: Hello, Guest
Here, name has a default value of "Guest".

Keyword Arguments

You can pass arguments in any order by specifying their parameter names explicitly.
Example:
def introduce(name, age, city):
    print(f"My name is {name}, I am {age} years old and live in {city}.")

introduce(age=25, name="Bob", city="Delhi")
Output:
My name is Bob, I am 25 years old and live in Delhi.

Variable-Length Arguments

Sometimes, you don't know how many arguments a function will receive. Python provides two special symbols for such cases:

Symbol Description
*args Used to pass a variable number of non-keyword arguments
**kwargs Used to pass a variable number of keyword arguments
Example using args:
def total(*numbers):
    print(sum(numbers))

total(10, 20, 30, 40)
Output:
100
Example using kwargs:
def display(**info):
    for key, value in info.items():
        print(f"{key}: {value}")

display(name="Alice", age=22, city="Pune")
Output:
name: Alice
age: 22
city: Pune

*args vs **kwargs

In Python, arguments are the values you pass into a function when calling it. They are categorized based on how they are matched to the function's parameters.

1. Non-Keyword (Positional) Arguments

These are arguments passed without a name and are matched to parameters based strictly on their positional order. The first value passed goes to the first parameter, the second to the second, and so on.

Use a single asterisk (e.g., *args) in a function definition to accept a variable number of positional arguments. These are collected into a tuple. They must appear before keyword arguments in a function call.

2. Keyword (Named) Arguments

These are arguments preceded by an identifier (e.g., name="Alice") in a function call. Because they are explicitly named, you can pass them in any sequence.

Use double asterisks (e.g., **kwargs) in a function definition to accept a variable number of keyword arguments. These are collected into a dictionary. They improve code readability and allow you to skip optional arguments that have default values.
Example:
def demo_function(*args, **kwargs):
    print("args:", args)
    print("kwargs:", kwargs)

demo_function(10, 20, 30, name="John", city="Delhi")
Output:
args: (10, 20, 30)
kwargs: {'name': 'John', 'city': 'Delhi'}

Recursion in Python

Recursion is a technique where a function calls itself to solve a smaller instance of the same problem. Every recursive function must have a base condition to stop the recursion; otherwise, it will continue infinitely.
Example:
def factorial(n):
    if n == 0 or n == 1:
        return 1
    else:
        return n * factorial(n - 1)

print(factorial(5))  # Output: 120
Here, factorial() keeps calling itself with a smaller value until n == 1.

How Recursion Works (Step by Step)

Example: factorial(3)
factorial(3)
= 3 * factorial(2)
= 3 * (2 * factorial(1))
= 3 * (2 * 1)
= 6
Recursion continues breaking the problem until it reaches the base case, then combines the results backward.

Advantages of Functions

- Code Reusability โ€“ Write once, use multiple times.
- Modularity โ€“ Break large code into manageable parts.
- Readability โ€“ Code becomes easier to understand and maintain.
- Testing โ€“ Functions can be tested independently.

Summary

Functions make your Python code more modular, clean, and efficient. Understanding recursion gives you the power to solve complex problems elegantly โ€” such as factorials, Fibonacci sequences, and tree traversals.

Concept Description
Function Reusable block of code that performs a specific task
Parameters Inputs defined in the function definition
Arguments Actual values passed during function call
return Sends result back to caller
Default Argument Provides default values if not passed
Keyword Argument Passes values using parameter names
*args / **kwargs Handle variable number of arguments
Recursion Function calling itself for repetitive problems
In the next article, we'll explore Modules and Packages โ€” how to organize and reuse code across multiple files to build scalable Python applications.
Nagesh Chauhan
Nagesh Chauhan
Principal Engineer | Java ยท Spring Boot ยท Python ยท Microservices ยท AI/ML

Principal Engineer with 14+ years of experience in designing scalable systems using Java, Spring Boot, and Python. Specialized in microservices architecture, system design, and machine learning.

Share this Article

๐Ÿ’ฌ Comments

Join the discussion