Python 装饰器

Python 函数装饰器 - 菜鸟教程

https://www.runoob.com/w3cnote/python-func-decorators.html

参考:https://eastlakeside.gitbook.io/interpy-zh/decorators/(与本文完全一致)

一切皆对象

在函数中定义函数

从函数中返回函数

将函数作为参数传给另一个函数

你的第一个装饰器

装饰器让你在一个函数的前后去执行代码。

装饰器封装一个函数,并且用这样或者那样的方式来修改它的行为。

@ 符号?那只是一个简短的方式来生成一个被装饰的函数。

使用functools.wraps还原被重写了被装饰函数的名字和注释文档(docstring)

from functools import wraps

@wraps(a_func)

@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。

使用场景

授权(Authorization)

装饰器能有助于检查某个人是否被授权去使用一个web应用的端点(endpoint)。它们被大量使用于Flask和Django web框架中。

日志(Logging)

带参数的装饰器

在函数中嵌入装饰器

装饰器类

装饰器 - 廖雪峰

https://www.liaoxuefeng.com/wiki/1016959663602400/1017451662295584

现在,假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

本质上,decorator就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下:

1
2
3
4
5
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper

log()是一个decorator,接受一个函数作为参数,并返回一个函数。

decorator用法:

1
2
3
@log
def now():
print('2015-3-25')

如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,写出来会更复杂。比如,要自定义log的文本:

1
2
3
4
5
6
7
def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator

这个3层嵌套的decorator用法如下:

1
2
3
@log('execute')
def now():
print('2015-3-25')

__name__属性变化

1
2
3
4
5
6
7
8
import functools

def log(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper

或者针对带参数的decorator:

1
2
3
4
5
6
7
8
9
10
import functools

def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator

lru_cache 装饰器

https://juejin.cn/post/6939345971042058248

这里的lru_cache是什么意思和作用?*args为什么带星号

1
2
3
4
5
6
7
8
@lru_cache(maxsize=128)
def get_conf(*args):
# 建议您复制一个config_private.py放自己的秘密, 如API和代理网址, 避免不小心传github被别人看到
res = []
for arg in args:
r = read_single_conf_with_lru_cache(arg)
res.append(r)
return res

lru_cache是Python标准库中的一个装饰器,用于实现缓存功能。它可以缓存函数的返回值,以便在后续的调用中避免重新计算相同的输入值所对应的结果。这有助于提高函数的执行效率,特别是在需要计算代价较高的操作时。

具体来说:

  • lru_cache是Least Recently Used(LRU,最近最少使用)缓存的缩写,它会保留最近调用的函数的结果,并在缓存达到指定大小(由maxsize参数指定)时,自动淘汰最不常使用的结果,以保持缓存的大小。
  • maxsize参数指定缓存的最大大小,即最多保存多少个不同输入值的结果。如果没有指定maxsize,则缓存的大小会无限增长。
  • 当函数被装饰为@lru_cache(maxsize=128)时,函数的每个不同的参数组合(传递给*args的值)都会被缓存,以及它们对应的返回值。下次再次使用相同的参数调用函数时,如果参数组合已经在缓存中,函数不会再次执行,而是直接返回之前的结果。
  • 这里的*args是Python中的可变参数,它允许函数接受任意数量的位置参数。在get_conf函数中,*args表示接受任意数量的参数,这些参数将被传递到read_single_conf_with_lru_cache函数中。*用于解包参数,因为args是一个元组,*args会将元组中的每个元素作为单独的参数传递给函数。

总结:@lru_cache用于缓存函数的计算结果,*args用于接受任意数量的输入参数,并将它们传递给被装饰的函数。这可以提高函数的执行效率,特别是在需要多次调用相同参数的情况下。