@wraps 润饰器:让你的 Python 代码更加简短可恶 | 从简略实例来意识它

咱们在上一篇文章(Python实例来意识并发与并行)中用到了 @timer ,在函数定义时,加上一个小小的 @timer ,这样,函数执行完结后,就会主动在控制台汇报本人运行的工夫。

比方上面这样:

@timerdef piper():    for i in range(10000):        i = i * i ** 10piper()输入:timer: using 0.00600 s

实际上,这个计时器逻辑 @timer 是咱们本人用 Python 中的润饰器个性来实现的。

拆解逻辑

其实咱们不必润饰器,本人也能实现计时的逻辑。

def piper():    for i in range(10000):        i = i * i ** 10t = time.time()  # 记录函数开始时工夫piper()print(f"timer: using {time.time() - t :.5f} s")  # 获取函数运行工夫并打印

留神到咱们执行函数时,在其高低都包裹上了逻辑。如果咱们心愿函数自带计时逻辑,那么为了包住原函数,只能去新定义一个函数。

def time_wrapper(func):    # func 是一个函数    t = time.time()    func()    print(f"timer: using {time.time() - t :.5f} s")time_wrapper(piper)输入:timer: using 0.00600 s

咱们想测试某一个函数运行工夫时,将函数名输出到 time_wrapper 外面就好。

更优雅的改良

上述代码显然有毛病:

  • 咱们在编程时,心智累赘增大了;此外,代码更简短了
  • 如果咱们只是心愿函数新增一个性能,显然用 time_wrapper 是不行的,因为其并没有扭转 piper 自身

于是咱们请出明天的配角 润饰器@wraps 。

还用咱们的 timer 举例子,咱们让所有在 @timer 下的函数,都通过如下解决:

def timer(func):    @wraps(func)    def inner_func():        t = time.time()        rts = func()        print(f"timer: using {time.time() - t :.5f} s")        return rts    return inner_func

piper 为例,咱们经验了如下变动。

@timerdef 原始piper():    for i in range(10000):        i = i * i ** 10

实际上,当你再调用 piper 时,你的 piper 外部逻辑早已变为:

def 以后piper():    t = time.time()    rts = 原始piper()    print(f"timer: using {time.time() - t :.5f} s")    return rts

总结

本文简略与读者敌人们「科普」一下润饰器,留神到咱们这里实际上仅仅润饰了无参数的函数。其实,润饰器还有许多更加优雅用处,比方传入参数 *args, **kwargs ,润饰类 __call__ 等用法。期待当前我遇到好的利用场景,将教训分享给敌人们。

记得点个『在看』!

我是小拍,关注我!