@functools.wraps
时间: 2023-11-28 18:06:14 浏览: 43
`@functools.wraps` 是 Python 中的一个装饰器,它用于将一个函数的元信息(例如函数名、文档字符串、参数和返回值类型)传递给被装饰的函数。简单来说,它是一个用于保持对象属性的装饰器,特别是源函数的属性,例如它所属的模块和名称。
具体来说,`@functools.wraps` 函数会在执行被装饰的函数时,同时更新被装饰函数的元信息。这样做的好处是,如果有人从被装饰的函数那里继承了信息,他们将获得原始函数的元信息,而不是被装饰函数的元信息。这对于保持代码的可读性和可维护性非常重要。
这个装饰器通常用在函数定义中,如下所示:
```python
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# 函数体
return func(*args, **kwargs)
return wrapper
```
在这个例子中,`my_decorator` 是一个装饰器,它接受一个函数作为参数,并返回一个新的函数 `wrapper`。这个新的函数在调用时,会首先执行原始函数的代码,然后返回结果。同时,`@wraps(func)` 这部分代码会将原始函数的元信息传递给新的函数。
总的来说,`@functools.wraps` 是一个非常有用的装饰器,它可以帮助我们保持代码的整洁和可读性。
相关问题
@functools.wraps(func)有什么作用
`@functools.wraps(func)` 是一个装饰器,用于将一个函数的元信息(如函数名、参数列表、注释等)更新为被装饰函数的元信息,从而让被装饰函数看起来像是没有经过装饰器包装的原始函数。
具体来说,当我们使用装饰器来包装一个函数时,原始函数的元信息会被替换成装饰器函数的元信息,这可能会导致一些问题,比如函数名等元信息不一致,导致代码可读性和调试难度的增加。
`@functools.wraps(func)` 装饰器的作用就是将被装饰函数的元信息复制到装饰器函数中,从而保留原始函数的元信息,让装饰器函数看起来像是没有经过装饰器包装的原始函数。具体来说,`@functools.wraps(func)` 装饰器会将被装饰函数的元信息复制到装饰器函数中的对应元信息中,比如:
- `__module__`: 模块名
- `__name__`: 函数名
- `__qualname__`: 带模块名的函数名
- `__doc__`: 文档字符串
- `__annotations__`: 注解信息
- `__dict__`: 属性字典
举个例子,下面是一个带有装饰器的函数:
```python
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print("Calling function: {}".format(func.__name__))
return func(*args, **kwargs)
return wrapper
@my_decorator
def my_function(x, y):
"""This is a docstring."""
return x + y
print(my_function.__name__)
print(my_function.__doc__)
```
在上面的代码中,我们定义了一个装饰器 `my_decorator`,将其应用到函数 `my_function` 上。在装饰器中,我们使用 `@functools.wraps(func)` 装饰器将被装饰函数的元信息复制到装饰器函数中。
运行上面的代码,输出结果如下:
```
my_function
This is a docstring.
```
从输出结果可以看出,装饰器函数 `wrapper` 的元信息已经被更新为原始函数 `my_function` 的元信息,包括函数名、文档字符串等信息。这样,我们就可以在装饰器中访问原始函数的元信息,同时也可以保留原始函数的元信息,方便代码的调试和维护。
python 装饰器在wrapper中打印时间使用了 @functools.wraps(func)还会打印两遍的问题
这个问题通常出现在使用了 `@functools.wraps(func)` 修饰装饰器函数时。这是因为 `@functools.wraps(func)` 会将被装饰函数的元信息(比如函数名、参数列表等)复制到装饰器函数中,以便让装饰器函数看起来像是被装饰函数本身。但是,如果你在装饰器函数中也使用了 `@functools.wraps(func)` 修饰函数,那么这个过程就会重复进行,导致元信息被复制两次,从而打印两次时间。
解决这个问题的方法是在装饰器函数中只使用一次 `@functools.wraps(func)`,并将其放在最外层的函数上方。例如:
```python
import functools
import time
def timeit(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} took {(end_time - start_time):.6f}s")
return result
return wrapper
```
这样,`@functools.wraps(func)` 只会被调用一次,元信息只会被复制一次,打印时间也只会出现一次。
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)