Function Basics
Functon Definition and Invocation
# Basic function definition
def greet_user():
for count in range(3):
print("Welcome to Python")
greet_user()
def personalized_greet(username):
for count in range(3):
print(f"Hello {username}")
personalized_greet("Developer")
def repeated_greet(name, repetitions):
for count in range(repetitions):
print(f"Greetings {name}")
repeated_greet("Python", 3)
Module Testing Pattern
def sample_function():
print("Module name:", __name__)
if __name__ == "__main__":
sample_function()
Function Parameters
Parameter Types
# Positional parameters
def construct_sentence(subject, verb, object):
return " ".join([object, verb, subject])
print(construct_sentence("Python", "loves", "developers"))
# Keyword arguments
print(construct_sentence(object="Python", subject="developers", verb="loves"))
# Default parameters
def build_message(first, second, connector=" and "):
return first + connector + second
print(build_message("Hello", "World"))
print(build_message("Python", "Programming", " with "))
Variable-length Arguments
# *args for positional arguments
def process_arguments(*params):
print(f"Received {len(params)} arguments")
print(f"Second parameter: {params[1]}")
process_arguments("first", "second", "third")
# **kwargs for keyword arguments
def process_keywords(**keyword_args):
print(keyword_args)
process_keywords(x=10, y=20, z=30)
# Combined parameter types
def mixed_params(required, *args, **kwargs):
print(required, args, kwargs)
mixed_params(1, 2, 3, 4, a=10, b=20)
# Argument unpacking
values = (10, 20, 30, 40)
def unpack_example(a, b, c, d):
print(a, b, c, d)
unpack_example(*values)
Scope and Nested Functions
Variable Scope
counter = 100
def modify_counter():
global counter
counter = 200
print(counter)
print(counter) # 100
modify_counter() # 200
print(counter) # 200
Nested Functions
def outer_function():
value = 100
def inner_function():
nonlocal value
value = 200
print("Inner:", value)
inner_function()
print("Outer:", value)
outer_function()
Closures
Basic Closure Pattern
def create_multiplier(factor):
def multiplier(value):
return value * factor
return multiplier
double = create_multiplier(2)
triple = create_multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15
Stateful Closure
def position_tracker():
x, y = 0, 0
def move(dx, dy):
nonlocal x, y
x += dx
y += dy
print(f"Position: ({x}, {y})")
return move
movement = position_tracker()
movement(2, 3) # Position: (2, 3)
movement(-1, 1) # Position: (1, 4)
Decorators
Function Decorator
import time
def timing_decorator(func):
def wrapper():
start_time = time.time()
result = func()
end_time = time.time()
print(f"Execution time: {end_time - start_time:.2f} seconds")
return result
return wrapper
@timing_decorator
def slow_operation():
time.sleep(1)
print("Operation completed")
slow_operation()
Parameterized Decorator
import functools
def repeat_decorator(count=2):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for _ in range(count):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat_decorator(count=3)
def say_hello():
print("Hello!")
say_hello()
Lambda Expressions
Anonymous Functions
# Traditional function
def square(x):
return x * x
# Lambda equivalent
square_lambda = lambda x: x * x
print(square(4)) # 16
print(square_lambda(4)) # 16
# Using lambda with map
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared) # [1, 4, 9, 16, 25]
# Using lambda with filter
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # [2, 4]
Generators
Generator Functions
def number_generator(limit):
current = 0
while current < limit:
yield current
current += 1
for num in number_generator(5):
print(num)
gen = number_generator(3)
print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 2
Fibonacci Generator
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
for _ in range(10):
print(next(fib))
Generator Expressions
squares = (x**2 for x in range(5))
print(list(squares)) # [0, 1, 4, 9, 16]
Recursive Functions
Basic Recursion
def countdown(n):
if n <= 0:
print("Done!")
else:
print(n)
countdown(n - 1)
countdown(5)
Tower of Hanoi
def hanoi_tower(disks, source, auxiliary, target):
if disks == 1:
print(f"Move disk from {source} to {target}")
else:
hanoi_tower(disks - 1, source, target, auxiliary)
print(f"Move disk from {source} to {target}")
hanoi_tower(disks - 1, auxiliary, source, target)
hanoi_tower(3, 'A', 'B', 'C')
Functon Documentation and Intorspection
Function Documentation
def calculate_area(length, width):
"""
Calculate the area of a rectangle.
Args:
length: The length of the rectangle
width: The width of the rectangle
Returns:
The area of the rectangle
"""
return length * width
print(help(calculate_area))
Type Annotations
def repeat_text(text: str, times: int) -> str:
return text * times
def process_items(items: list[int], multiplier: int = 2) -> list[int]:
return [item * multiplier for item in items]
print(repeat_text("Hi", 3))
print(process_items([1, 2, 3]))
Introspection
def sample_function(x: int, y: str) -> bool:
"""A sample function for introspection."""
return len(y) > x
print(sample_function.__name__)
print(sample_function.__annotations__)
print(sample_function.__doc__)
Higher-Order Functions
Reduce Function
import functools
def multiply(a, b):
return a * b
numbers = [1, 2, 3, 4, 5]
product = functools.reduce(multiply, numbers)
print(product) # 120
# Using lambda
factorial = functools.reduce(lambda x, y: x * y, range(1, 6))
print(factorial) # 120
Partial Functions
from functools import partial
def power(base, exponent):
return base ** exponent
square = partial(power, exponent=2)
cube = partial(power, exponent=3)
print(square(5)) # 25
print(cube(3)) # 27