Completed
-
1. Introduction to Python
-
2. Python Basics
-
3. Working with Data Structures
-
4. Functions and Modules
-
5. Object-Oriented Programming (OOP)
-
6. File Handling
-
7. Error and Exception Handling
-
8. Python for Data Analysis
-
9. Advanced Topics in Python
-
10. Working with APIs
-
11. Python for Automation
-
12. Capstone Projects
- 13. Final Assessment and Quizzes
9.2 Decorators
Decorators are a powerful and flexible feature in Python, allowing you to modify or extend the behavior of functions or methods without changing their code. They are often used for logging, access control, memoization, and other tasks that involve modifying or enhancing existing functions.
1. What are Decorators?
A decorator is a function that takes another function (or method) as an argument and extends or alters its behavior. You can think of a decorator as a wrapper that "wraps" the original function and can modify its behavior before or after the function is called.
Decorators are commonly used for:
- Code reusability: Apply a certain behavior across multiple functions without modifying each one.
- Separation of concerns: Add functionality (like logging, validation, or authentication) to functions without modifying their core logic.
- Aspect-oriented programming: Keep concerns like logging or caching separate from business logic.
2. How Decorators Work
In Python, decorators work by using higher-order functions. A higher-order function is a function that takes another function as an argument and returns a function.
Basic Syntax of a Decorator:
def decorator_function(original_function): def wrapper_function(): print("Wrapper function executed before {}".format(original_function.__name__)) return original_function() # Call the original function return wrapper_function # Return the wrapper function @decorator_function # This is equivalent to: my_function = decorator_function(my_function) def my_function(): print("Hello, World!") my_function()
Output:
Wrapper function executed before my_function Hello, World!
In the above example:
- decorator_function is a decorator that takes my_function as an argument and returns the wrapper_function.
- The @decorator_function syntax is a shorthand for passing my_function to the decorator.
3. Decorators with Arguments
You can also pass arguments to the function wrapped by the decorator. The decorator function can accept arguments if needed, making it more flexible.
Example: A Decorator with Arguments
def decorator_with_args(arg): def decorator_function(original_function): def wrapper_function(*args, **kwargs): print(f"Decorator argument value: {arg}") return original_function(*args, **kwargs) return wrapper_function return decorator_function @decorator_with_args("Hello") def greet(name): print(f"Hello, {name}!") greet("Alice")
Output:
Decorator argument value: Hello Hello, Alice!
In this example, the decorator decorator_with_args takes an argument arg and passes it to the wrapper_function, which can use it as needed.
4. Built-in Python Decorators
Python provides several built-in decorators that are commonly used in Python programming. Some of them include:
a) @staticmethod
A static method doesn’t require access to the instance or class and is usually used for utility functions.
class MyClass: @staticmethod def greet(name): print(f"Hello, {name}") MyClass.greet("Bob")
b) @classmethod
A class method takes cls as the first argument and can be used to modify class state.
class MyClass: @classmethod def greet(cls, name): print(f"Hello, {name} from class {cls.__name__}") MyClass.greet("Charlie")
5. Chaining Decorators
Multiple decorators can be applied to the same function. The decorators are applied bottom to top, meaning the decorator closest to the function is applied first.
Example: Chaining Decorators
def decorator_one(func): def wrapper(): print("Decorator One") return func() return wrapper def decorator_two(func): def wrapper(): print("Decorator Two") return func() return wrapper @decorator_one @decorator_two def hello(): print("Hello, World!") hello()
Output:
Decorator One Decorator Two Hello, World!
Here, decorator_two is applied first, and then decorator_one is applied to the resulting wrapped function.
6. Using Decorators for Function Memoization
One common use of decorators is for memoization, where results of expensive function calls are cached so that subsequent calls with the same arguments are faster.
Example: Memoization Decorator
def memoize(func): cache = {} def wrapper(*args): if args not in cache: print(f"Calculating result for {args}") cache[args] = func(*args) return cache[args] return wrapper @memoize def expensive_function(n): return n * n print(expensive_function(4)) print(expensive_function(4)) # This time, it uses the cached result
Output:
Calculating result for (4,) 16 16
Here, the memoize decorator stores the results of function calls so that repeated calls with the same arguments do not need to be recomputed.
7. Using Decorators for Logging and Validation
Decorators are commonly used for tasks like logging and validation. For example, you can create a decorator that logs function calls or validates inputs before the function is executed.
Example: Logging Decorator
def log_function_call(func): def wrapper(*args, **kwargs): print(f"Function {func.__name__} was called with arguments {args} and keyword arguments {kwargs}") return func(*args, **kwargs) return wrapper @log_function_call def add(a, b): return a + b add(2, 3)
Output:
Function add was called with arguments (2, 3) and keyword arguments {}
8. Summary of Decorators
- A decorator is a function that takes another function and modifies or enhances its behavior.
- Decorators are useful for logging, access control, memoization, and other cross-cutting concerns.
- Python's @decorator syntax is a shorthand for applying decorators to functions.
- Decorators are applied in bottom to top order if multiple decorators are used.
- Decorators can also accept arguments and be used with built-in decorators like @staticmethod and @classmethod.
Decorators are a powerful feature in Python that allow you to extend the functionality of existing code without modifying the original functions. They are commonly used in web development, data processing, and many other areas where additional functionality is needed for functions or methods.
Commenting is not enabled on this course.