如何写出高性能的Python之修饰符functools.wraps

2022-01-24 13:36:37 浏览数 (1)

  其实整个functools模块都值得讲一下,我们后面会出一个专门的文章来讲。今天我们先来看下functools.wraps。

  在本节内容开始前,首先要了解什么是修饰符?可以参考我们之前整理的一篇文章。

Python高性能计算之修饰符

这这篇文章中我们可以看到,修饰器的一般形式是:

代码语言:javascript复制
def works_for_all(func):
    def inner(*args, **kwargs):
        print("I can decorate any function")
        return func(*args, **kwargs)
    return inner

@works_for_all
def ff(*args, **kwargs):
    print(args)
    print(kwargs)

如果我们此时打印ff的名字:

代码语言:javascript复制
print(ff.__name__)
>>> inner

可以看到,由于使用了修饰符,函数的__name__属性已经被修改成了修饰器中闭包函数的名字。这样会导致什么问题呢?如果两个函数的修饰符都是works_for_all,那么这两个函数的名字就一样了。

代码语言:javascript复制
@works_for_all
def ff2(*args, **kwargs):
    return 1

打印出两个函数的名字:

代码语言:javascript复制
print(ff.__name__)
>>> inner
print(ff2.__name__)
>>> inner

如何解决这个问题呢?即便使用了修饰符,__name__属性应该还是保持原来的函数名,此时functools.wraps就派上用场了。

代码语言:javascript复制
from functools import wraps
def works_for_all(func):
    @wraps(func)
    def inner(*args, **kwargs):
        print("I can decorate any function")
        return func(*args, **kwargs)
    return inner

@works_for_all
def ff(*args, **kwargs):
    print(args)
    print(kwargs)

@works_for_all
def ff2(*args, **kwargs):
    return 1

增加@functools.wraps(func), 可以保持当前装饰器去装饰的函数的 name 的值不变.

此时再打印两个函数的名字:

代码语言:javascript复制
print(ff.__name__)
print(ff2.__name__)
>>> ff
>>> ff2

0 人点赞