Python Function
Defining a Function
To define a function, use the def keyword followed by the function name and
parentheses () which may include parameters.
The function body starts with a colon : and is indented.
Syntax
def function_name(parameters):
"""
Docstring: Description of the function.
"""
# Function body
statement(s)
return value # Optional
Example of a Simple Function
In [1]: def greet(name):
"""
This function greets the person whose name is passed as a parameter.
"""
print(f"Hello, {name}!")
Calling a Function
To call a function, use the function name followed by parentheses containing
arguments.
In [2]: greet("Alice")
Hello, Alice!
In [3]: greet('jon')
Hello, jon!
Function Parameters
Functions can accept parameters to make them more flexible.
1. Positional Parameters
Parameters are passed in the order they are defined.
In [4]: def add(a, b):
return a + b
1/6
result = add(3, 5)
print(result)
In [5]: add(5,8)
13
Out[5]:
2. Default Parameters
You can provide default values for parameters.
In [6]: def greet(name, message="Hello"):
print(f"{message}, {name}!")
print(name,message)
In [7]: greet("jon")
Hello, jon!
jon Hello
3. Keyword Arguments
You can pass arguments using the parameter names, allowing you to skip or rearrange them.
In [8]: def describe_pet(pet_name, animal_type="dog"):
print(f"I have a {animal_type} named {pet_name}.")
In [9]: describe_pet(pet_name="Whiskers", animal_type="cat")
I have a cat named Whiskers.
In [10]: describe_pet("Buddy")
I have a dog named Buddy.
4. Variable-Length Arguments
*args (Non-Keyword Arguments)
Allows you to pass a variable number of non-keyword arguments to a function.
In [11]: def sum_all(*args):
return sum(args)
In [12]: print(sum_all(1, 2, 3, 4))
10
In [13]: print(sum_all(5, 10))
15
5. **kwargs (Keyword Arguments)
Allows you to pass a variable number of keyword arguments.
In [14]: def print_info(**kwargs):
for key, value in kwargs.items():
2/6
print(f"{key}: {value}")
In [15]: print_info(name="Alice", age=30, city="New York")
name: Alice
age: 30
city: New York
In [16]: def show_info(*args, **kwargs):
"""
This function prints positional arguments and keyword arguments.
"""
print("Positional arguments:", args)
print("Keyword arguments:", kwargs)
In [17]: show_info(1, 2, 3, 4,"s",1.3,True, name="Bob", age=25, city="San Francisco")
Positional arguments: (1, 2, 3, 4, 's', 1.3, True)
Keyword arguments: {'name': 'Bob', 'age': 25, 'city': 'San Francisco'}
Returning Values
Functions can return values using the return statement. If no return statement is used,
the function returns None by default.
In [18]: def square(x):
return x * x
result = square(4)
print(result)
16
Lambda Functions
Lambda functions are small anonymous functions defined using the lambda keyword. They
can have any number of arguments but only one expression.
In [19]: square = lambda x: x * x
print(square(5))
25
In [20]: add = lambda a, b: a + b
print(add(3, 4))
Scope and Lifetime of Variables
Local Scope: Variables declared inside a function are local to that function.
Global Scope: Variables declared outside any function are global and can be accessed
anywhere in the code.
In [21]: x = 100 # Global variable
def my_fun():
x =50 # Local variable
3/6
print(x)
def my_fun1():
x =60 # Local variable
print(x)
def my_fun2():
print(x)
In [22]: my_fun()
50
In [23]: my_fun1()
60
In [24]: print(x)
100
In [25]: my_fun2()
100
In [26]: x = 300
def myfunc():
global x
x = 400
In [27]: print(x)
300
In [28]: myfunc()
In [29]: print(x)
400
In [30]: print(x)
400
Recursion in Python
Recursion is a programming technique where a function calls itself to solve smaller
instances of the same problem.
This approach can simplify the solution for problems that exhibit self-similarity and can
be broken down into simpler sub-problems.
Components of a Recursive Function
1. Base Case: The condition under which the recursion stops. Without a base case, the
function would call itself indefinitely, leading to a stack overflow.
2. Recursive Case: The part of the function where it calls itself with a smaller or simpler
argument. This step moves the problem toward the base case.
4/6
Detailed Examples
Example 1: Factorial Calculation
The factorial of a non-negative integer ( n ) is the product of all positive integers less than or
equal to ( n ). The factorial of ( n ) is denoted as ( n! ). For example:
[ 5! = 5 \times 4 \times 3 \times 2 \times 1 = 120 ]
Here's the recursive definition:
Base Case: ( 0! = 1 ) (by definition) and ( 1! = 1 ).
Recursive Case: ( n! = n \times (n-1)! )
In [31]: def factorial(n):
"""
Calculate the factorial of a non-negative integer n using recursion.
"""
# Base case: if n is 0 or 1, return 1
if n == 0 or n == 1:
return 1
# Recursive case: n! = n * (n-1)!
else:
return n * factorial(n - 1)
print(factorial(5))
print(factorial(0))
print(factorial(3))
120
1
6
In this function:
When n is 0 or 1, it returns 1.
Otherwise, it calls itself with n-1 and multiplies the result by n .
Example 2: Fibonacci Sequence
The Fibonacci sequence is a series where each number is the sum of the two preceding ones,
starting from 0 and 1. The sequence is defined as:
Base Cases: ( F(0) = 0 ) and ( F(1) = 1 )
Recursive Case: ( F(n) = F(n-1) + F(n-2) )
In [32]: def fibonacci(n):
"""
Calculate the nth Fibonacci number using recursion.
"""
# Base case: return n if n is 0 or 1
if n == 0 or n == 1:
return n
# Recursive case: F(n) = F(n-1) + F(n-2)
else:
return fibonacci(n - 1) + fibonacci(n - 2)
5/6
print(fibonacci(5))
print(fibonacci(6))
5
8
Recursion vs. Iteration
While recursion can simplify the code for certain problems, it is important to understand
when to use it over iteration.
Recursion can be less efficient and more memory-intensive due to the call stack
overhead.
Iterative solutions, on the other hand, can be more efficient but sometimes more
complex to write and understand.
6/6