What Are Decorators?
In Python, functions are first-class citizens. This means they can be passed around as arguments to other functions, returned as values from other functions, and even assigned to variables. Decorators leverage this feature to extend or modify the behavior of target functions.
Basic Syntax
The basic syntax for decorators involves the “@” symbol, followed by the name of the decorator function. This is placed just above the function intended to be decorated. Think of decorator syntax as syntactic sugar.
@decorator_functiondef target_function():print("Target function executed.")@decorator_function def target_function(): print("Target function executed.")@decorator_function def target_function(): print("Target function executed.")
Enter fullscreen mode Exit fullscreen mode
How Does It Work?
When you use a decorator, you are essentially doing three things:
Passing the target function as an argument to the decorator function.
Modifying or extending the behavior of the target function within the decorator function.
Returning the modified function or even a completely new function from the decorator function.
def decorator_function(target_function):def wrapper_function():print("Before the target function.")target_function()print("After the target function.")return wrapper_function@decorator_functiondef say_hello():print("Hello!")say_hello()def decorator_function(target_function): def wrapper_function(): print("Before the target function.") target_function() print("After the target function.") return wrapper_function @decorator_function def say_hello(): print("Hello!") say_hello()def decorator_function(target_function): def wrapper_function(): print("Before the target function.") target_function() print("After the target function.") return wrapper_function @decorator_function def say_hello(): print("Hello!") say_hello()
Enter fullscreen mode Exit fullscreen mode
When you call say_hello()
, it actually executes wrapper_function()
. This, in turn, calls the original say_hello()
function between two print statements. The output would be:
Before the target function.Hello!After the target function.Before the target function. Hello! After the target function.Before the target function. Hello! After the target function.
Enter fullscreen mode Exit fullscreen mode
Chaining Decorators
Decorators can be chained, meaning you can apply multiple decorators to a single function:
def decorator_one(func):def wrapper_one():print("Decorator one: Before calling the function.")func()print("Decorator one: After calling the function.")return wrapper_onedef decorator_two(func):def wrapper_two():print("Decorator two: Before calling the function.")func()print("Decorator two: After calling the function.")return wrapper_two@decorator_one@decorator_twodef my_function():print("The original function.")my_function()def decorator_one(func): def wrapper_one(): print("Decorator one: Before calling the function.") func() print("Decorator one: After calling the function.") return wrapper_one def decorator_two(func): def wrapper_two(): print("Decorator two: Before calling the function.") func() print("Decorator two: After calling the function.") return wrapper_two @decorator_one @decorator_two def my_function(): print("The original function.") my_function()def decorator_one(func): def wrapper_one(): print("Decorator one: Before calling the function.") func() print("Decorator one: After calling the function.") return wrapper_one def decorator_two(func): def wrapper_two(): print("Decorator two: Before calling the function.") func() print("Decorator two: After calling the function.") return wrapper_two @decorator_one @decorator_two def my_function(): print("The original function.") my_function()
Enter fullscreen mode Exit fullscreen mode
Here, my_function
is first passed to decorator_two
, and then the result is passed on to decorator_one
. The output for this code would be:
Decorator one: Before calling the function.Decorator two: Before calling the function.The original function.Decorator two: After calling the function.Decorator one: After calling the function.Decorator one: Before calling the function. Decorator two: Before calling the function. The original function. Decorator two: After calling the function. Decorator one: After calling the function.Decorator one: Before calling the function. Decorator two: Before calling the function. The original function. Decorator two: After calling the function. Decorator one: After calling the function.
Enter fullscreen mode Exit fullscreen mode
Class Decorators
During my time at Flatiron School, I came across a few useful class decorators:
@staticmethod
- A static method is bound to the class itself and not to an instance of the class.
- These methods serve as utility functions that operate on their parameters.
Example:
class MyClass:def __init__(self,name):self.name = self.capitalize_name(name)@staticmethoddef capitalize_name(name):return name.capitalize()instance1 = MyClass('john')print(instance1.name)class MyClass: def __init__(self,name): self.name = self.capitalize_name(name) @staticmethod def capitalize_name(name): return name.capitalize() instance1 = MyClass('john') print(instance1.name)class MyClass: def __init__(self,name): self.name = self.capitalize_name(name) @staticmethod def capitalize_name(name): return name.capitalize() instance1 = MyClass('john') print(instance1.name)
Enter fullscreen mode Exit fullscreen mode
The output would be:
JohnJohnJohn
Enter fullscreen mode Exit fullscreen mode
@classmethod
- Similar to a static method, a class method is bound to the class and not an instance of the class.
- The first parameter for a class method is
cls
, which stands for ‘class’. - Class methods can access or modify the class state.
Example:
class MyClass:def __init__(self,name):self.name = name@classmethoddef create_with_capitalized_name(cls,name):name = name.capitalize()return cls(name)instance1 = MyClass.create_with_capitalized_name('john')print(instance1.name)class MyClass: def __init__(self,name): self.name = name @classmethod def create_with_capitalized_name(cls,name): name = name.capitalize() return cls(name) instance1 = MyClass.create_with_capitalized_name('john') print(instance1.name)class MyClass: def __init__(self,name): self.name = name @classmethod def create_with_capitalized_name(cls,name): name = name.capitalize() return cls(name) instance1 = MyClass.create_with_capitalized_name('john') print(instance1.name)
Enter fullscreen mode Exit fullscreen mode
The output would be:
'John''John''John'
Enter fullscreen mode Exit fullscreen mode
There’s a whole world of decorators out there, but these are the key ones that I’ve encountered on my Python learning journey at Flatiron School. I genuinely hope you’ve found this article to be a helpful guide. I’m always open to feedback, so feel free to share your thoughts. Thanks so much for taking the time to read!
原文链接:Understanding Python Decorators: A Practical Introduction
暂无评论内容