Functions are reusable blocks of code that perform specific tasks. They help organize code and avoid repetition.
# Basic function definition
def greet():
print("Hello, World!")
# Calling the function
greet() # Output: Hello, World!
# Function with parameters
def greet_person(name):
print(f"Hello, {name}!")
greet_person("Alice") # Output: Hello, Alice!
# Function with return value
def add_numbers(a, b):
result = a + b
return result
sum_result = add_numbers(5, 3)
print(sum_result) # Output: 8
# Positional parameters
def introduce(name, age, city):
return f"Hi, I'm {name}, {age} years old, from {city}"
print(introduce("Bob", 25, "Boston"))
# Default parameters
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
print(greet("Alice")) # Hello, Alice!
print(greet("Bob", "Hi")) # Hi, Bob!
# Keyword arguments
def create_profile(name, age, city="Unknown", occupation="Student"):
return {
"name": name,
"age": age,
"city": city,
"occupation": occupation
}
profile1 = create_profile("Alice", 22)
profile2 = create_profile("Bob", 30, occupation="Engineer", city="Seattle")
print(profile1)
print(profile2)
# *args - variable number of positional arguments
def sum_all(*numbers):
total = 0
for num in numbers:
total += num
return total
print(sum_all(1, 2, 3)) # 6
print(sum_all(1, 2, 3, 4, 5)) # 15
# **kwargs - variable number of keyword arguments
def create_student(**info):
student = {}
for key, value in info.items():
student[key] = value
return student
student1 = create_student(name="Alice", age=20, major="Computer Science")
student2 = create_student(name="Bob", grade="A", subject="Math")
print(student1)
print(student2)
# Combining all parameter types
def flexible_function(required, *args, default="default", **kwargs):
print(f"Required: {required}")
print(f"Args: {args}")
print(f"Default: {default}")
print(f"Kwargs: {kwargs}")
flexible_function("must_have", 1, 2, 3, default="custom", extra="info")
# Basic lambda function
square = lambda x: x ** 2
print(square(5)) # 25
# Lambda with multiple parameters
add = lambda x, y: x + y
print(add(3, 4)) # 7
# Using lambda with built-in functions
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))
print(squared) # [1, 4, 9, 16, 25]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # [2, 4]
# Sorting with lambda
students = [("Alice", 85), ("Bob", 90), ("Charlie", 78)]
students.sort(key=lambda student: student[1]) # Sort by grade
print(students) # [('Charlie', 78), ('Alice', 85), ('Bob', 90)]
# Local vs Global scope
global_var = "I'm global"
def test_scope():
local_var = "I'm local"
print(global_var) # Can access global variable
print(local_var) # Can access local variable
test_scope()
print(global_var) # Can access global variable
# print(local_var) # Error! local_var not accessible here
# Modifying global variables
counter = 0
def increment():
global counter
counter += 1
increment()
increment()
print(counter) # 2
# Nested functions and nonlocal
def outer_function():
x = 10
def inner_function():
nonlocal x
x += 5
print(f"Inner x: {x}")
inner_function()
print(f"Outer x: {x}")
outer_function()
# Functions that take other functions as arguments
def apply_operation(numbers, operation):
result = []
for num in numbers:
result.append(operation(num))
return result
def double(x):
return x * 2
def square(x):
return x ** 2
numbers = [1, 2, 3, 4, 5]
doubled = apply_operation(numbers, double)
squared = apply_operation(numbers, square)
print(doubled) # [2, 4, 6, 8, 10]
print(squared) # [1, 4, 9, 16, 25]
# Functions that return other functions
def create_multiplier(factor):
def multiplier(x):
return x * factor
return multiplier
times_2 = create_multiplier(2)
times_3 = create_multiplier(3)
print(times_2(5)) # 10
print(times_3(4)) # 12
# Factorial using recursion
def factorial(n):
if n == 0 or n == 1: # Base case
return 1
else:
return n * factorial(n - 1) # Recursive case
print(factorial(5)) # 120
# Fibonacci sequence
def fibonacci(n):
if n <= 1:
return n
else:
return fibonacci(n - 1) + fibonacci(n - 2)
for i in range(10):
print(fibonacci(i), end=" ") # 0 1 1 2 3 5 8 13 21 34
# Binary search (recursive)
def binary_search(arr, target, left=0, right=None):
if right is None:
right = len(arr) - 1
if left > right:
return -1 # Not found
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] > target:
return binary_search(arr, target, left, mid - 1)
else:
return binary_search(arr, target, mid + 1, right)
sorted_list = [1, 3, 5, 7, 9, 11, 13, 15]
index = binary_search(sorted_list, 7)
print(f"Found at index: {index}") # Found at index: 3
# Docstrings for function documentation
def calculate_area(length, width):
"""
Calculate the area of a rectangle.
Args:
length (float): The length of the rectangle
width (float): The width of the rectangle
Returns:
float: The area of the rectangle
Example:
>>> calculate_area(5, 3)
15
"""
return length * width
# Accessing docstring
print(calculate_area.__doc__)
# Type hints (Python 3.5+)
def greet_user(name: str, age: int) -> str:
"""Greet a user with their name and age."""
return f"Hello {name}, you are {age} years old!"
# Function annotations
def process_data(data: list, multiplier: float = 1.0) -> list:
"""Process data by multiplying each element."""
return [x * multiplier for x in data]