装饰器通过函数作为第一类对象实现,定义一个接收函数的装饰器,在其内部定义wrapper函数并添加额外逻辑,最后返回wrapper;使用@语法糖将原函数替换为包装后的函数,从而在不修改原函数代码的情况下增强功能。

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象。 它们经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理等等。
装饰器就像给函数穿上了一件“外衣”,这件“外衣”可以给函数增加额外的能力,但不会改变函数本身。
Python的装饰器是基于函数是“第一类对象”这一概念实现的。这意味着函数可以像任何其他对象一样被传递、赋值和作为返回值。
简单来说,装饰器通过以下步骤工作:
立即学习“Python免费学习笔记(深入)”;
当使用
@decorator
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()这段代码的执行结果是:
Something is happening before the function is called. Hello! Something is happening after the function is called.
如果被装饰的函数带有参数,wrapper函数需要能够接收和传递这些参数。可以使用
*args
**kwargs
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Before calling the function")
result = func(*args, **kwargs)
print("After calling the function")
return result
return wrapper
@my_decorator
def add(a, b):
return a + b
print(add(2, 3))输出结果:
Before calling the function After calling the function 5
装饰器可以做的远不止日志和性能监控。 它们可以用于:
例如,一个简单的缓存装饰器:
import functools
def cache(func):
cached_values = {}
@functools.wraps(func)
def wrapper(*args):
if args in cached_values:
return cached_values[args]
else:
result = func(*args)
cached_values[args] = result
return result
return wrapper
@cache
def expensive_operation(n):
print(f"Calculating for {n}...")
return n * n
print(expensive_operation(5))
print(expensive_operation(5)) # 从缓存中获取除了函数装饰器,Python还支持类装饰器。 类装饰器接收一个函数或类作为参数,并返回一个修改后的函数或类。
类装饰器通常通过实现
__call__
__call__
class MyDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("Before calling the function")
result = self.func(*args, **kwargs)
print("After calling the function")
return result
@MyDecorator
def say_hello(name):
print(f"Hello, {name}!")
say_hello("Alice")有时候,我们需要一个可以接收参数的装饰器。 这可以通过创建一个返回装饰器函数的函数来实现。
def repeat(num_times):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
@repeat(num_times=3)
def greet(name):
print(f"Hello, {name}!")
greet("Bob")这个例子中,
repeat
num_times
decorator_repeat
decorator_repeat
func
默认情况下,装饰器会改变被装饰函数的元数据,例如
__name__
__doc__
help()
为了解决这个问题,可以使用
functools.wraps
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
"""This is the wrapper function."""
print("Before calling the function")
result = func(*args, **kwargs)
print("After calling the function")
return result
return wrapper
@my_decorator
def say_hello():
"""This is the original function."""
print("Hello!")
print(say_hello.__name__)
print(say_hello.__doc__)使用了
functools.wraps
say_hello.__name__
say_hello
say_hello.__doc__
This is the original function.
functools.wraps
可以同时使用多个装饰器来增强一个函数的功能,这就是装饰器链。 装饰器的应用顺序是从下往上,从里到外。
def bold(func):
def wrapper(*args, **kwargs):
return "<b>" + func(*args, **kwargs) + "</b>"
return wrapper
def italic(func):
def wrapper(*args, **kwargs):
return "<i>" + func(*args, **kwargs) + "</i>"
return wrapper
@bold
@italic
def get_message(message):
return message
print(get_message("Hello"))在这个例子中,
get_message
italic
bold
<b><i>Hello</i></b>
以上就是python中的装饰器是如何工作的_python装饰器工作原理与实例详解的详细内容,更多请关注php中文网其它相关文章!
python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号