Functions
1. Function Definition
A function is a reusable block of code that performs a specific task, often taking input, processing it, and returning an output. Functions help organize code, make it modular, and avoid repetition.
- Defined using the
defkeyword, followed by the function name, parentheses (), and a colon : - Optional inputs (arguments) passed inside the parentheses.
- Use
returnto send back a result (optional; defaults to None if omitted). - Execute a function by using its name followed by parentheses, passing arguments if needed.
def greet(name): # Function definition with parameter 'name'
message = f"Hello, {name}!"
return message # Returns a greeting
#Calling the function
print(greet("Alice")) # Output: Hello, Alice!
2. Parameters and Arguments
a) Positional Parameters
Positional parameters (or positional arguments) are function arguments passed in the order they are defined in the function's parameter list. When calling the function, the values are matched to the parameters based on their position
def add(a, b):
return a + b
# Positional arguments: 3 maps to 'a', 4 maps to 'b'
result = add(3+4)
print(result) # Output: 7
b) Default Parameters
Default parameters allow you to specify default values for function parameters, making them optional when the function is called. If an argument for a default parameter is not provided, the default value is used.
def greet(name="Guest"):
return f"Hello, {name}!"
print(greet()) # Output: Hello, Guest!
print(greet("Bob")) # Output: Hello, Bob!
c) Keyword Arguments
Keyword arguments (or named arguments) are function arguments passed by explicitly specifying the parameter name and its value in the format parameter=value. This allows you to pass arguments in any order, unlike positional arguments.
def person_info(name, age):
return f"{name} is {age} years old"
# Using keyword arguments
print(person_info(age=25, name="Charlie")) # Output: Charlie is 25 years old
d) Variable-length Arguments
Variable-length arguments allow a function to accept a varying number of arguments, either as a tuple (*args) for positional arguments or as a dictionary (**kwargs) for keyword arguments. This makes functions flexible when the number of inputs isn't fixed.
*args:Collects extra positional arguments into a tuple.
Used when you want to pass a variable number of non-keyword arguments.**kwargs:Collects extra keyword arguments into a dictionary.
Used for a variable number of named arguments.- args and kwargs are conventional names, but the * and ** syntax is what matters
Using **args
def sum_numbers(*args):
return sum(args)
print(sum_numbers(1, 2, 3)) # Output: 6
print(sum_numbers(10)) # Output: 10
print(sum_numbers()) # Output: 0
Using **kwargs
def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_info(name="Alice", age=25, city="Paris")
# Output:
# name: Alice
# age: 25
# city: Paris
3. Return Statement
Exits function and returns value(s).
def multiply(a, b):
return a * b
def get_coordinates():
return 1, 2
result = multiply(3, 4) # result = 12
x, y = get_coordinates() # x = 1, y = 2
5. Lambda Functions
A lambda function is a small, anonymous function defined using the lambda keyword. It can have any number of arguments but only one expression, which is evaluated and returned. Lambda functions are often used for short, simple operations, especially in places where a full function definition is unnecessary, like with map(), filter(), or sorting.
Syntax
lambda arguments: expression
# Basic Lambda function to add two numbers
add = lambda x, y: x + y
print(add(3, 5)) # Output: 8
# Basic Lambda function to square a number
square = lambda x: x * x
print(square(5)) # Output: 25
Using map() function:
numbers = [1, 2, 3, 4]
squared = list(map(lambda x: x**2, numbers))
print(squared) # Output: [1, 4, 9, 16]
Using filter() function:
numbers = [1, 2, 3, 4, 5, 6]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # Output: [2, 4, 6]
6. Function Decorators
Function decorators are a way to modify or extend the behavior of a function without directly changing its source code. A decorator is a higher-order function that takes a function as input, wraps it with additional functionality, and returns a new function. Decorators are commonly used for tasks like logging, timing, access control, or memoization.
Note: Modify functions without changing their code.def my_decorator(func):
def wrapper():
print("Before the function")
func()
print("After the function")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# Output:
# Before the function
# Hello!
# After the function
7. Recursion
Recursion is a process where a function calls itself to solve a problem by breaking it into smaller, similar subproblems. It’s useful for tasks that have a naturally recursive structure, like tree traversals or factorial calculations, but requires careful design to avoid infinite loops or excessive memory use.
Factorial:def factorial(n):
if n == 0 or n == 1:
return 1
return n * factorial(n - 1)
print(factorial(5)) # Output: 120
Fibonacci Sequence:
def fibonacci(n):
# Base cases
if n <= 0:
return 0
if n == 1:
return 1
# Recursive case
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(6)) # Output: 8 (0, 1, 1, 2, 3, 5, 8)