函数包装是做什么的?

函数包装是做什么的?

在对此的评论中回答另一个问题有人说他们不确定functools.wraps在做什么。因此,我提出这个问题,以便在StackOverflow上有一个记录,供将来参考:functools.wraps真的吗?



三国纷争
浏览 873回答 3
3回答

慕勒3428872

当您使用装饰器时,您将一个函数替换为另一个函数。换句话说,如果你有一个装饰师def logged(func):     def with_logging(*args, **kwargs):         print(func.__name__ + " was called")         return func(*args, **kwargs)     return with_logging当你说@loggeddef f(x):    """does some math"""    return x + x * x这和说def f(x):     """does some math"""     return x + x * x f = logged(f)以及你的功能f将其替换为_LOGING函数。不幸的是,这意味着如果你说print(f.__name__)它会打印出来with_logging因为这是你新功能的名字。实际上,如果您查看docstringf,它将是空白的,因为with_logging没有docstring,所以您编写的docstring将不再存在。另外,如果您查看该函数的pydoc结果,它将不会被列为接受一个参数x相反,它将被列为*args和**kwargs因为这就是日志记录所需要的。如果使用装饰器总是意味着丢失有关函数的信息,那么这将是一个严重的问题。所以我们才有functools.wraps..这使用了一个在装饰器中使用的函数,并添加了对函数名、docstring、参数列表等进行复制的功能。wraps它本身就是一个装饰器,下面的代码做的是正确的事情:from functools import wrapsdef logged(func):     @wraps(func)     def with_logging(*args, **kwargs):         print(func.__name__ + " was called")         return func(*args, **kwargs)     return with_logging@loggeddef f(x):    """does some math"""    return x + x * xprint(f.__name__)  # prints 'f'print(f.__doc__)   # prints 'does some math'

倚天杖

我经常使用类,而不是函数,作为我的装饰师。我在这方面遇到了一些问题,因为一个对象不会拥有函数所期望的所有相同的属性。例如,对象将不具有属性__name__..我对此有一个特定的问题,很难跟踪Django报告的错误“Object无属性”__name__“。不幸的是,对于类风格的装饰师,我不认为@PARY能够胜任这项工作。相反,我创建了一个基本的装饰类,如下所示:class DecBase(object):     func = None     def __init__(self, func):         self.__func = func    def __getattribute__(self, name):         if name == "func":             return super(DecBase, self).__getattribute__(name)         return self.func.__getattribute__(name)     def __setattr__(self, name, value):         if name == "func":             return super(DecBase, self).__setattr__(name, value)         return self.func.__setattr__(name, value)这个类代理所有属性调用正在被修饰的函数。因此,您现在可以创建一个简单的装饰器,检查是否指定了2个参数,如下所示:class process_login(DecBase):     def __call__(self, *args):         if len(args) != 2:             raise Exception("You can only specify two arguments")         return self.func(*args)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python