Decorators and Metaprogramming

Understanding Decorators and Their Purpose

Decorators are a powerful feature in Python that allow you to modify the behavior of functions or classes by wrapping them with other functions. Decorators provide a concise way to add functionality to existing code without modifying the original implementation. They are widely used for tasks such as logging, timing, authentication, and more.

  1. YouTube Video: "Python Decorators - Demystified" Link: Python Decorators - Demystified

Examples

Example 1: Simple Function Decorator

def uppercase_decorator(func):
    def wrapper():
        original_result = func()
        modified_result = original_result.upper()
        return modified_result
    return wrapper

@uppercase_decorator
def say_hello():
    return "hello"

print(say_hello())

Example 2: Class Decorator

def add_custom_method(cls):
    def custom_method(self):
        return "This is a custom method"
    cls.custom_method = custom_method
    return cls

@add_custom_method
class MyClass:
    pass

obj = MyClass()
print(obj.custom_method())

Exercises

Exercise 1: Question: What is a decorator in Python? Answer: A decorator is a design pattern in Python that allows you to modify the behavior of a function or class by wrapping it with another function. Decorators provide a way to add additional functionality to existing code without modifying the original implementation.

Exercise 2: Question: How do you define a decorator in Python? Answer: A decorator is defined as a function that takes a function or class as an argument, defines a wrapper function that modifies the behavior, and returns the wrapper function.

Exercise 3: Question: How do you apply a decorator to a function or class? Answer: To apply a decorator to a function or class, you can use the @decorator_name syntax above the function or class definition.

Exercise 4: Question: What are some use cases for decorators? Answer: Decorators are often used for tasks such as logging, timing, input validation, authentication, memoization, and more. They provide a clean and reusable way to add common functionality to multiple functions or classes.

Exercise 5: Question: Can a decorator take arguments? Answer: Yes, decorators can take arguments. In such cases, you need to define an additional outer function that accepts the arguments and returns the actual decorator function.

Creating and Using Decorators

Decorators are a powerful feature in Python that allow you to modify the behavior of functions or classes by wrapping them with other functions. In this topic, we will explore how to create decorators and apply them to functions or classes to add additional functionality or modify their behavior.

  1. YouTube Video: "Python Decorators - A Complete Guide" Link: Python Decorators - A Complete Guide

Examples

Example 1: Simple Function Decorator

def uppercase_decorator(func):
    def wrapper():
        original_result = func()
        modified_result = original_result.upper()
        return modified_result
    return wrapper

@uppercase_decorator
def say_hello():
    return "hello"

print(say_hello())

Example 2: Decorator with Arguments

def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            results = []
            for _ in range(n):
                result = func(*args, **kwargs)
                results.append(result)
            return results
        return wrapper
    return decorator

@repeat(3)
def greet(name):
    return f"Hello, {name}!"

print(greet("Alice"))

Exercises

Exercise 1: Question: How do you create a decorator in Python? Answer: To create a decorator, define a function that takes a function as an argument, defines a wrapper function inside it, and returns the wrapper function.

Exercise 2: Question: How do you apply a decorator to a function? Answer: To apply a decorator to a function, use the @decorator_name syntax above the function definition.

Exercise 3: Question: Can a decorator accept arguments? Answer: Yes, a decorator can accept arguments. In such cases, you need to define an additional outer function that accepts the arguments and returns the actual decorator function.

Exercise 4: Question: Can decorators modify function arguments or return values? Answer: Yes, decorators can modify function arguments and return values. Inside the wrapper function, you can access and modify the arguments and return values as needed.

Exercise 5: Question: Can decorators be applied to class methods? Answer: Yes, decorators can be applied to class methods in a similar way as they are applied to functions.

Writing Class Decorators

Class decorators in Python allow you to modify the behavior of classes by wrapping them with other classes. They provide a way to add additional functionality or modify the behavior of class methods, attributes, or the class itself. In this topic, we will explore how to write class decorators and apply them to classes.

  1. YouTube Video: "Python Class Decorators - A Comprehensive Guide" Link: Python Class Decorators - A Comprehensive Guide

Examples

Example 1: Simple Class Decorator

def add_custom_method(cls):
    class ModifiedClass(cls):
        def custom_method(self):
            return "This is a custom method"
    return ModifiedClass

@add_custom_method
class MyClass:
    pass

obj = MyClass()
print(obj.custom_method())

Example 2: Class Decorator with Arguments

def add_prefix(prefix):
    def decorator(cls):
        class ModifiedClass(cls):
            def __init__(self, name):
                self.name = prefix + name
        return ModifiedClass
    return decorator

@add_prefix("Hello, ")
class Greeting:
    def __init__(self, name):
        self.name = name

obj = Greeting("Alice")
print(obj.name)

Exercises

Exercise 1: Question: How do you create a class decorator in Python? Answer: To create a class decorator, define a function that takes a class as an argument, defines a modified class inside it, and returns the modified class.

Exercise 2: Question: How do you apply a class decorator to a class? Answer: To apply a class decorator to a class, use the @decorator_name syntax above the class definition.

Exercise 3: Question: Can a class decorator modify class methods or attributes? Answer: Yes, class decorators can modify class methods, attributes, or even the class itself by defining a modified version of the class with additional or modified behavior.

Exercise 4: Question: Can class decorators accept arguments? Answer: Yes, class decorators can accept arguments. In such cases, you need to define an additional outer function that accepts the arguments and returns the actual decorator function.

Exercise 5: Question: Can multiple class decorators be applied to a single class? Answer: Yes, you can apply multiple class decorators to a single class by stacking them using the @decorator syntax.

Metaprogramming Techniques Using Decorators

Metaprogramming refers to the ability to write code that manipulates or generates other code at runtime. Decorators in Python can be used as a powerful tool for metaprogramming, allowing you to dynamically modify or generate code. In this topic, we will explore some metaprogramming techniques using decorators.

  1. YouTube Video: "Python Metaprogramming with Decorators" Link: Python Metaprogramming with Decorators

Examples

Example 1: Logging Decorator

def logging_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Calling function: {func.__name__}")
        result = func(*args, **kwargs)
        print(f"Function {func.__name__} returned: {result}")
        return result
    return wrapper

@logging_decorator
def add(a, b):
    return a + b

print(add(2, 3))

Example 2: Parameterized Decorator

def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            results = []
            for _ in range(n):
                result = func(*args, **kwargs)
                results.append(result)
            return results
        return wrapper
    return decorator

@repeat(3)
def greet(name):
    return f"Hello, {name}!"

print(greet("Alice"))

Exercises

Exercise 1: Question: How can decorators be used for code generation in Python? Answer: Decorators can be used for code generation by dynamically modifying or generating code at runtime. By wrapping functions or classes with decorators, you can add or change functionality based on certain conditions or inputs.

Exercise 2: Question: Can decorators modify the behavior of a function or class based on runtime conditions? Answer: Yes, decorators can modify the behavior of a function or class based on runtime conditions. By using conditional statements or other logic inside the decorator, you can dynamically alter the behavior of the decorated code.

Exercise 3: Question: Can decorators be used to implement memoization? Answer: Yes, decorators can be used to implement memoization, which is a technique that caches the results of expensive function calls and returns the cached result when the same inputs are encountered again.

Exercise 4: Question: How can decorators be used for access control or authentication? Answer: Decorators can be used to enforce access control or authentication by wrapping functions or methods with decorators that check the user's credentials or permissions before allowing the execution of the decorated code.

Exercise 5: Question: Can decorators modify the attributes or methods of a class dynamically? Answer: Yes, decorators can modify the attributes or methods of a class dynamically by wrapping the class with a decorator that adds, modifies, or removes attributes or methods.

Last updated

Was this helpful?