理解Python装饰器看这一篇就够了("Python装饰器详解:一文彻底掌握核心原理与用法")
原创
一、装饰器简介
在Python中,装饰器是一种非常有用的功能,它允许我们以不修改原有函数定义的方案,扩展或愈发函数的行为。装饰器在很多高级Python框架和库中都有广泛的应用,例如Flask、Django等。
二、装饰器的核心原理
装饰器本质上是一个返回函数的函数。它接收一个函数作为参数,然后返回一个新的函数,这个新的函数会在执行原函数之前或之后,增多一些额外的功能。
三、装饰器的使用方法
下面我们来通过一个简洁的例子来了解装饰器的使用方法。
3.1 无参数装饰器
首先,我们定义一个无参数的装饰器。
def my_decorator(func):
def wrapper():
print("Before the function is called.")
func()
print("After the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello, world!")
say_hello()
执行上述代码,输出最终如下:
Before the function is called.
Hello, world!
After the function is called.
3.2 带参数的装饰器
接下来,我们来看一个带参数的装饰器。
def repeat(num):
def decorator(func):
def wrapper():
for _ in range(num):
func()
return wrapper
return decorator
@repeat(3)
def say_hello():
print("Hello, world!")
say_hello()
执行上述代码,输出最终如下:
Hello, world!
Hello, world!
Hello, world!
四、装饰器的进阶用法
装饰器除了可以用来扩展函数的功能,还可以用来实现一些高级功能,如缓存、日志记录等。
4.1 缓存装饰器
下面我们来实现一个简洁的缓存装饰器,它会将函数的返回值缓存起来,如果再次调用相同的参数,则直接返回缓存的最终,而不是重新计算。
def memoize(func):
cache = {}
def memoized_func(*args):
if args in cache:
return cache[args]
result = func(*args)
cache[args] = result
return result
return memoized_func
@memoize
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))
执行上述代码,输出最终如下:
55
4.2 日志装饰器
下面我们来实现一个简洁的日志装饰器,它会记录函数的调用和返回值。
import logging
def log(func):
def wrapper(*args, **kwargs):
logging.info(f"Calling function {func.__name__} with args {args} and kwargs {kwargs}")
result = func(*args, **kwargs)
logging.info(f"Function {func.__name__} returned {result}")
return result
return wrapper
@log
def add(a, b):
return a + b
add(3, 4)
执行上述代码,输出最终如下(假设logging配置正确):
INFO:root:Calling function add with args (3, 4) and kwargs {}
INFO:root:Function add returned 7
五、装饰器的高级用法
除了基本的装饰器用法,Python还赞成一些高级的装饰器特性,如装饰器类、装饰器参数等。
5.1 装饰器类
装饰器类允许我们使用面向对象的方案来定义装饰器。下面是一个装饰器类的例子:
class MyDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("Before the function is called.")
result = self.func(*args, **kwargs)
print("After the function is called.")
return result
@MyDecorator
def say_hello():
print("Hello, world!")
say_hello()
执行上述代码,输出最终如下:
Before the function is called.
Hello, world!
After the function is called.
5.2 装饰器参数
装饰器本身也可以接受参数,这需要我们在装饰器内部再定义一个函数来接收这些参数。下面是一个装饰器参数的例子:
def count_calls(func):
def wrapper(*args, **kwargs):
wrapper.calls += 1
return func(*args, **kwargs)
wrapper.calls = 0
return wrapper
@count_calls
def say_hello():
print("Hello, world!")
say_hello()
say_hello()
print(f"say_hello has been called {say_hello.calls} times.")
@count_calls
def add(a, b):
return a + b
add(3, 4)
add(5, 6)
print(f"add has been called {add.calls} times.")
执行上述代码,输出最终如下:
Hello, world!
Hello, world!
say_hello has been called 2 times.
7
11
add has been called 2 times.
六、总结
装饰器是Python中一种非常强盛的功能,它允许我们以模块化和可重用的方案扩展或愈发函数的行为。通过本文的介绍,我们了解了装饰器的基本原理、使用方法、进阶用法和高级用法。愿望这篇文章能够帮助你彻底掌握Python装饰器的核心原理与用法。