0% completed
In this lesson, we explore the functionality of decorators in Python, starting with understanding how functions in Python can be treated as first-class objects. We will demonstrate this with simple examples and then explore why decorators are essential for enhancing the functionality of functions without altering their core definition.
Functions in Python are first-class objects, meaning they can be passed around and used as arguments just like any other object.
This example shows how to assign a function to a variable:
Explanation:
def greet():
defines a simple function that prints a greeting.greet_func = greet
assigns the greet
function to the variable greet_func
.greet_func()
calls the function using the new variable name, demonstrating that the function behaves like an object.Functions can be passed as arguments to other functions:
Explanation:
shout
and whisper
functions change the case of the text.explain
function takes another function and a string, applies the function to the string, and prints the result.explain(shout, "Hello")
and explain(whisper, "Hello")
demonstrate dynamic function passing.Decorators provide a way to modify functions using other functions without changing the function's source code. This capability is particularly useful for adding features like logging, access control, memoization, and more.
Here’s a basic decorator that adds logging functionality to any function it decorates:
Explanation:
def logger(func):
The logger
function defines the decorator accepting func
, the function to be decorated.logger
, wrapper
is defined which encapsulates the added functionality. Before calling the func
, it logs "Logging execution...", then calls func()
, and logs "Done logging." after the function executes.@logger
is used to apply the decorator to the sample
function. When sample()
is called, it first executes the logging statements, then the original function body.This example shows a decorator that accepts parameters, allowing for more dynamic behavior:
Explanation:
def repeat(times):
This is a decorator factory that takes times
as an argument, which specifies how many times the decorated function should be repeated.decorator_repeat(func):
Defines the actual decorator that wraps the function func
.wrapper(*args, **kwargs):
The wrapper function that repeats the function call as many times as specified by times
. It accepts any number of positional and keyword arguments to pass to func
.func
.When a function that returns values or takes arguments is decorated, the decorator must be properly designed to handle these aspects.
Here is a decorator that performs type checking for function arguments:
Explanation:
type_check
is applied to sum_numbers
. It ensures that every argument passed to sum_numbers
is an integer.ValueError
.Applying multiple decorators to a function is known as chaining. Each decorator adds its layer of functionality in the order specified.
Here, both logging and type checking functionalities are added to a function:
Explanation:
@type_check
ensures all arguments are integers and then @logger
logs the execution.Decorators are extensively used in web frameworks to map URLs to functions that generate web pages:
Explanation:
Initialization: An empty dictionary named routes
is created. This dictionary will be used to store URL paths as keys and corresponding functions as values.
Decorator Definition: A function named route
is defined. This function takes a path as an argument and returns a decorator function.
Decorator Usage: The route
decorator is used to associate specific URL paths with functions. For example, @route("/home")
associates the /home
URL path with the home_page
function, and @route("/about")
associates the /about
URL path with the about_page
function.
Function Definition: Functions like home_page
and about_page
are defined. These functions represent the content of different pages of a hypothetical website.
Request Simulation: The simulate_request
function is defined to simulate a web request to a specified path. It takes a path as an argument and prints the result of executing the function associated with that path.
Execution: The simulate_request
function is called twice, once with the /home
path and once with the /about
path. This simulates visiting the home page and the about page of the simulated website, respectively.
Output: The content of the requested pages is printed to the console.
Decorators thus serve as powerful tools for enhancing and organizing Python code, especially in complex applications where modularity, reusability, and cleanliness are crucial.
.....
.....
.....