理解python的decorator中的函数包装器
我有两个python装饰器实现的示例。我想知道它们在函数包装器实现方面有什么不同。他们的工作方式一样吗?有什么背景差异吗?做函数包装器的pythonic方法是什么 例1 例2理解python的decorator中的函数包装器,python,decorator,wrapper,Python,Decorator,Wrapper,我有两个python装饰器实现的示例。我想知道它们在函数包装器实现方面有什么不同。他们的工作方式一样吗?有什么背景差异吗?做函数包装器的pythonic方法是什么 例1 例2 首先,我们正在寻找一种比装饰师更复杂的东西。decorator是一个函数,它接受一个函数作为输入并返回一个函数。在这里,顶级函数返回decorators。因此,它们实际上也是上述意义上的装饰器,即使通常所称的装饰器是第一个内部函数。此定义方案通常用于创建参数化装饰器 这样看来,您是在专门询问functools.wrapps
首先,我们正在寻找一种比装饰师更复杂的东西。decorator是一个函数,它接受一个函数作为输入并返回一个函数。在这里,顶级函数返回decorators。因此,它们实际上也是上述意义上的装饰器,即使通常所称的装饰器是第一个内部函数。此定义方案通常用于创建参数化装饰器 这样看来,您是在专门询问functools.wrapps。如果是这样的话,我只能敦促你看看医生
基本上,它用于使装饰器返回的函数看起来与装饰的函数相同,即:具有相同的名称、docstring等。您在问什么?这个装饰器使它成为可用的关于包装函数的信息,而不是关于包装器的信息。但是使用它真的是必要的吗?第二个例子没有使用它,并且可以工作。您可以编写没有它的decorator,但是它们往往会使获取包装函数的数据变得困难。因此,如果您想读取包装函数的docstring,或者知道它的名称等,如果不使用包装,这是非常困难的。这被认为是良好的实践:您可能永远不需要该功能,但您永远不知道,如果您提供这些装饰器供其他人使用,他们可能需要它。它也不会伤害任何东西。我想不出使用wrapsIt有什么坏处,它不需要让代码正常工作,同样,注释、文档和良好的编码风格也不需要。functools.wrapps复制函数的名称、docstring和其他内容,这使其他人更容易使用修饰过的函数,并允许您访问未修饰过的函数。没有理由不使用它。感谢Aran和Patrick,我将修改代码中的第二个示例以使用@wrapps:谢谢你,阿尼斯,我去看看。因此,出于您指出的这些原因,更倾向于使用@wrapps,对吗?
from functools import wraps
def retry(times=3, waiting_time=30):
'''
Decorator to retry any functions 'times' times.
Parameters
----------
times: int
Number of times to retry to execute
waiting_time: int
Number of times to wait between retries
'''
def retry_decorator(func):
# My doubt is here.
@wraps(func)
def retried_function(*args, **kwargs):
for i in range(times):
try:
return func(*args, **kwargs)
except Exception as err:
print(f'Try nº {i+1}')
sleep(waiting_time)
func(*args, **kwargs)
return retried_function
return retry_decorator
def exception(logger):
'''
Decorator that wraps the passed function and logs
exceptions when it occurs.
Parameters
----------
logger : logging object
Object to use to log exceptions
'''
def decorator(func):
# Here the function wrapper is different from example 1
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
# log the exception
err = "There was an exception in "
err += func.__name__
logger.exception(err)
# re-raise the exception
raise
return wrapper
return decorator