functools.wraps是做什么的? [英] What does functools.wraps do?

查看:90
本文介绍了functools.wraps是做什么的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在对此的评论中回答另一个问题,有人说他们不确定functools.wraps在做什么.所以,我问这个问题,以便在StackOverflow上记录下来,以备将来参考:functools.wraps到底是做什么的?

In a comment on this answer to another question, someone said that they weren't sure what functools.wraps was doing. So, I'm asking this question so that there will be a record of it on StackOverflow for future reference: what does functools.wraps do, exactly?

推荐答案

使用装饰器时,您将一个函数替换为另一个.换句话说,如果您有装饰器

When you use a decorator, you're replacing one function with another. In other words, if you have a decorator

def logged(func):
    def with_logging(*args, **kwargs):
        print(func.__name__ + " was called")
        return func(*args, **kwargs)
    return with_logging

然后当你说

@logged
def f(x):
   """does some math"""
   return x + x * x

这和说的完全一样

def f(x):
    """does some math"""
    return x + x * x
f = logged(f)

,并且您的函数f被函数with_logging代替.不幸的是,这意味着如果您再说

and your function f is replaced with the function with_logging. Unfortunately, this means that if you then say

print(f.__name__)

它将打印with_logging,因为这是新功能的名称.实际上,如果您查看f的文档字符串,它将为空,因为with_logging没有文档字符串,因此您编写的文档字符串将不再存在.另外,如果您查看该函数的pydoc结果,它将不会被列为带有一个参数x.而是将其列为*args**kwargs,因为with_logging就是这样.

it will print with_logging because that's the name of your new function. In fact, if you look at the docstring for f, it will be blank because with_logging has no docstring, and so the docstring you wrote won't be there anymore. Also, if you look at the pydoc result for that function, it won't be listed as taking one argument x; instead it'll be listed as taking *args and **kwargs because that's what with_logging takes.

如果使用装饰器总是意味着丢失有关功能的信息,那将是一个严重的问题.这就是为什么我们有functools.wraps的原因.这将使用装饰器中使用的功能,并添加复制功能名称,文档字符串,参数列表等的功能.由于wraps本身是装饰器,因此以下代码可以正确执行操作:

If using a decorator always meant losing this information about a function, it would be a serious problem. That's why we have functools.wraps. This takes a function used in a decorator and adds the functionality of copying over the function name, docstring, arguments list, etc. And since wraps is itself a decorator, the following code does the correct thing:

from functools import wraps
def logged(func):
    @wraps(func)
    def with_logging(*args, **kwargs):
        print(func.__name__ + " was called")
        return func(*args, **kwargs)
    return with_logging

@logged
def f(x):
   """does some math"""
   return x + x * x

print(f.__name__)  # prints 'f'
print(f.__doc__)   # prints 'does some math'

这篇关于functools.wraps是做什么的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆