Python Function Programming: Parameters, Closures, Decorators, and Advanced Concepts

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

Tags: python functions decorators closures generators

Posted on Sun, 28 Jun 2026 16:53:17 +0000 by austrainer