Python Functions¶
What is a Function in Python?¶
- A function is a block of reusable code that performs a specific task. Functions help organize code, improve modularity, and enable code reuse.
Key Features of Functions¶
- A function runs only when it is called.
- Functions allow passing parameters (input data).
- They can return a value as an output.
- Defined using the
def
keyword in Python. - Enhances code reusability and modularity.
In [ ]:
# Defining a simple function
def welcome_message():
"""This function prints a welcome message."""
print("Welcome to Intensity Coding")
# Calling the function
welcome_message()
#Expected Output: Welcome to Intensity Coding
Welcome to Intensity Coding
Defining a Function in Python¶
A function in Python is defined using the
def
keyword, followed by:- A function name.
- Parentheses
()
(to hold parameters, if any). - An optional docstring (a brief description of the function).
- A colon (
:
) to start the function block. - An indented code block inside the function.
- A return statement (optional) to send back a result.
Syntax of a Function¶
def function_name(parameters):
"""Optional docstring"""
# Function logic here
return value # Optional return statement
In [ ]:
# Example: Function with Parameters and Return Value
# Function to add two numbers
def add_numbers(a, b):
"""Returns the sum of two numbers"""
return a + b # Returning the sum
# Calling the function and printing the result
result = add_numbers(5, 10)
print("Sum:", result)
#Output: Sum: 15
Sum: 15
Calling a Function in Python¶
- Once a function is defined, it can be called by using its name followed by parentheses
()
.
In [ ]:
# Defining a function
def greet():
"""Prints a greeting message"""
print("Hello from Intensity Coding!")
# Calling the function
greet()
#Output: Hello from Intensity Coding!
Hello from Intensity Coding!
Example: Calling a Function with Arguments¶
In [ ]:
# Function with parameters
def greet_user(name):
"""Greets the user with a personalized message"""
print(f"Hello, {name}! Welcome to Intensity Coding.")
# Calling function with an argument
greet_user("Alice")
# Output: Hello, Alice! Welcome to Intensity Coding.
Hello, Alice! Welcome to Intensity Coding.
Pass by Reference vs Value in Python¶
Pass by Reference in Python¶
- In Python, all parameters (arguments) are passed by reference. This means if a function modifies a mutable object (like a list), the change will be reflected outside the function as well.
In [ ]:
# Example: Pass by Reference (Mutable Object)
# Function modifies the list by appending elements
def changeme(mylist):
"""Appends new elements to the list"""
mylist.append([1, 2, 3, 4])
print("Values inside the function:", mylist)
# Creating a list
mylist = [10, 20, 30]
# Calling the function
changeme(mylist)
# Checking the list after function call
print("Values outside the function:", mylist)
# Output:
# Values inside the function: [10, 20, 30, [1, 2, 3, 4]]
# Values outside the function: [10, 20, 30, [1, 2, 3, 4]]
Values inside the function: [10, 20, 30, [1, 2, 3, 4]] Values outside the function: [10, 20, 30, [1, 2, 3, 4]]
Example: Overwriting the Reference (Pass by Value Behavior)¶
- When a new object is assigned to a parameter inside the function, the original reference is lost, and changes do not reflect outside.
In [ ]:
# Function assigns a new list, breaking the reference
def changeme(mylist):
"""Assigns a new list inside the function"""
mylist = [1, 2, 3, 4] # Assigns a new reference
print("Values inside the function:", mylist)
# Creating a list
mylist = [10, 20, 30]
# Calling the function
changeme(mylist)
# Checking the list after function call
print("Values outside the function:", mylist)
# Output:
# Values inside the function: [1, 2, 3, 4]
# Values outside the function: [10, 20, 30]
Values inside the function: [1, 2, 3, 4] Values outside the function: [10, 20, 30]
Function Arguments in Python¶
- Functions can accept arguments (parameters), which are values passed during a function call.
Types of Function Arguments:¶
- Required Arguments
- Keyword Arguments
- Default Arguments
- Variable-Length Arguments
Parameters vs Arguments in Python¶
The terms parameters and arguments are often used interchangeably, but they have distinct meanings:
Parameter: A variable listed in the function definition.
Argument: The actual value passed to a function when calling it.
In [ ]:
# Function with parameters
def greet_user(name):
"""Greets the user with a personalized message"""
print(f"Hello, {name}! Welcome to Intensity Coding.")
# Calling function with an argument
greet_user("Alice")
# Output: Hello, Alice! Welcome to Intensity Coding.
Hello, Alice! Welcome to Intensity Coding.
Number of Arguments in Python Functions¶
- By default, a function must be called with the correct number of arguments. If the function expects two arguments, it must be called with exactly two.
In [ ]:
# Example: Function with Multiple Arguments
# Function with two parameters
def my_function(fname, lname):
"""Prints full name"""
print(fname + " " + lname)
# Calling function with two arguments
my_function("Emil", "Refsnes")
# Output: Emil Refsnes
Emil Refsnes
In [ ]:
# Example: Missing an Argument (Causes Error)
# Function expecting two parameters
def my_function(fname, lname):
"""Prints full name"""
print(fname + " " + lname)
# Uncommenting below will raise an error
# my_function("Emil") # TypeError: my_function() missing 1 required positional argument: 'lname'
Required Arguments¶
- A required argument must be passed when calling a function; otherwise, Python raises an error.
In [ ]:
# Function that prints a given string
def printme(string):
"""Prints the given string"""
print(string)
# Calling function with required argument
printme("Hello, Intensity Coding!")
# Output: Hello, Intensity Coding!
# Uncommenting the below line will cause an error
# printme() # TypeError: printme() missing 1 required argument
Hello, Intensity Coding!
Keyword Arguments¶
- Python allows passing arguments using key-value pairs (
key=value
). - The order of arguments does not matter when using keyword arguments.
In [ ]:
# Function to configure an AI model using keyword arguments
def configure_model(optimizer, loss_function, activation):
"""Prints AI model settings using keyword arguments"""
print("Model Configuration:")
print(f"Optimizer: {optimizer}")
print(f"Loss Function: {loss_function}")
print(f"Activation Function: {activation}")
# Calling function with keyword arguments in different orders
configure_model(optimizer="Adam", loss_function="MSE", activation="ReLU")
# Output:
# Model Configuration:
# Optimizer: Adam
# Loss Function: MSE
# Activation Function: ReLU
print("----------")
configure_model(loss_function="CrossEntropy", activation="Sigmoid", optimizer="SGD")
# Output:
# Model Configuration:
# Optimizer: SGD
# Loss Function: CrossEntropy
# Activation Function: Sigmoid
Model Configuration: Optimizer: Adam Loss Function: MSE Activation Function: ReLU ---------- Model Configuration: Optimizer: SGD Loss Function: CrossEntropy Activation Function: Sigmoid
Default Parameter Value¶
- A default parameter is used when an argument is not provided.
In [ ]:
# Function with default training settings
def train_model(learning_rate=0.01, batch_size=32, epochs=10):
"""Prints training settings with default values"""
print(f"Training with learning_rate={learning_rate}, batch_size={batch_size}, epochs={epochs}")
# Calling function with custom values
train_model(0.001, 64, 20)
# Output: Training with learning_rate=0.001, batch_size=64, epochs=20
# Calling function without arguments (uses default values)
train_model()
# Output: Training with learning_rate=0.01, batch_size=32, epochs=10
Training with learning_rate=0.001, batch_size=64, epochs=20 Training with learning_rate=0.01, batch_size=32, epochs=10
Variable-Length Arguments¶
Arbitrary Arguments (*args
)¶
- If you don’t know how many arguments will be passed into a function, use
*args
. - The function receives arguments as a tuple and can access them using indexing.
In [ ]:
# Function to print multiple AI models
def list_models(*models):
"""Prints a list of AI models provided as arguments"""
print("Available AI Models:")
for model in models:
print(model)
# Calling function with multiple model names
list_models("Decision Tree", "Neural Network", "Random Forest")
# Output:
# Available AI Models:
# Decision Tree
# Neural Network
# Random Forest
Available AI Models: Decision Tree Neural Network Random Forest
In [ ]:
# Function with Required and Arbitrary Arguments
# Function to print a required dataset name and optional features
def dataset_info(dataset_name, *features):
"""Prints dataset name and additional feature details"""
print("Dataset Name:", dataset_name)
print("Features:")
for feature in features:
print(feature)
# Calling function with different numbers of features
dataset_info("Image Dataset")
# Output:
# Dataset Name: Image Dataset
# Features:
print("----------")
dataset_info("Image Dataset", "Grayscale", "Size: 28x28 pixels")
# Output:
# Dataset Name: Image Dataset
# Features:
# Grayscale
# Size: 28x28 pixels
Dataset Name: Image Dataset Features: ---------- Dataset Name: Image Dataset Features: Grayscale Size: 28x28 pixels
Arbitrary Keyword Arguments(**kwargs)¶
- If you don’t know how many keyword arguments will be passed, use
**kwargs
. - The function receives arguments as a dictionary.
In [ ]:
# Function to print dataset details
def dataset_details(**info):
"""Prints dataset details dynamically"""
print("Dataset Details:")
for key, value in info.items():
print(f"{key}: {value}")
# Calling function with dataset details
dataset_details(name="MNIST", samples=60000, image_size="28x28 pixels")
# Output:
# Dataset Details:
# name: MNIST
# samples: 60000
# image_size: 28x28 pixels
Dataset Details: name: MNIST samples: 60000 image_size: 28x28 pixels
Positional-Only and Keyword-Only Arguments¶
- Python allows specifying whether function arguments must be passed positionally or as keyword arguments.
Positional-Only Arguments¶
- To enforce positional-only arguments, add
/
after them.
In [ ]:
def multiply(x, /):
"""Multiplies a given number by 2. Requires a positional argument."""
print(x * 2)
# Correct usage (positional argument)
multiply(5) # Output: 10
# Incorrect usage (keyword argument, raises TypeError)
# multiply(x=5)
10
Keyword-Only Arguments¶
- To enforce keyword-only arguments, add
*
before them.
In [ ]:
def multiply(*, x):
"""Multiplies a given number by 2. Requires a keyword argument."""
print(x * 2)
# Correct usage (keyword argument)
multiply(x=5) # Output: 10
# Incorrect usage (positional argument, raises TypeError)
# multiply(5)
10
Combining Positional-Only and Keyword-Only¶
- You can define functions that require both positional-only and keyword-only arguments.
In [ ]:
def compute(a, b, /, *, c, d):
"""Computes a calculation using mixed argument types."""
print((a + b) * (c - d))
# Correct usage
compute(5, 6, c=8, d=3) # Output: 55
# Incorrect usages (raises TypeError)
# compute(a=5, b=6, c=8, d=3)
# compute(5, 6, 8, 3)
55
Return Values in Python¶
- Functions in Python can return values using the
return
statement. This allows us to reuse the computed value elsewhere in the program. - It helps in reusing function output , improves code modularity and makes functions more flexible.
In [ ]:
def square_number(x):
"""Calculates the square of the given number and returns the result."""
return x ** 2
# Calling the function and printing the results
print(square_number(3)) # Output: 9
print(square_number(5)) # Output: 25
print(square_number(9)) # Output: 81
9 25 81
The pass
Statement¶
- Python does not allow empty function definitions. If you need to define a function without implementing it yet, you can use the
pass
statement. - It helps prevents syntax errors when defining an empty function and useful for creating placeholders in large projects.
In [ ]:
def future_function():
"""This function will be implemented later."""
pass # Placeholder to avoid errors
# Calling the function (does nothing)
future_function()
Recursion in Python¶
- Recursion is when a function calls itself. It is commonly used in problems involving mathematical calculations (factorial, Fibonacci series) and Tree and graph traversals.
Key Considerations When Using Recursion¶
- Every recursive function must have a base case to avoid infinite recursion.
- Recursive functions can consume a lot of memory if not handled correctly.
In [ ]:
def recursive_sum(n):
"""
Recursively calculates the sum of all numbers from n to 0.
"""
if n > 0:
result = n + recursive_sum(n - 1) # Recursive call
print(f"Summing: {n}, Current Sum: {result}")
else:
result = 0 # Base case
return result
# Calling the recursive function
print("\nRecursion Example Results:")
recursive_sum(6)
#Output:
# Summing: 1, Current Sum: 1
# Summing: 2, Current Sum: 3
# Summing: 3, Current Sum: 6
# Summing: 4, Current Sum: 10
# Summing: 5, Current Sum: 15
# Summing: 6, Current Sum: 21
# 21
Recursion Example Results: Summing: 1, Current Sum: 1 Summing: 2, Current Sum: 3 Summing: 3, Current Sum: 6 Summing: 4, Current Sum: 10 Summing: 5, Current Sum: 15 Summing: 6, Current Sum: 21
Out[ ]:
21