Python装饰器函数详解

对于现有函数来说,为了给其增加一些功能,但由于考虑到别处调用过该函数,因而不能直接在函数内部修改。通过函数闭包的特性,在不修改原有函数的情况下,可以通过装饰器来对其功能进行拓展。

python

0x00 装饰器的需求

在软件开发的过程中,难免需要对现有函数添加一些功能,而软件开发过程中一直遵循着一个“开放封闭原则”。

  • 开放:对于拓展是开发的
  • 封闭:对于修改是封闭的

因而不能直接对函数进行修改。由此通过一些列的代码及优化,形成了现有的装饰器函数。

装饰器函数:不想修改函数的调用方式,但是还想在原来的函数前后添加功能。

0x01 装饰器的形成

在有一个函数hw(),先想为其添加一个功能,可以输出函数的执行时间,下面是没有学装饰器的时候用的方法。

import time
#已有函数
def hw():
    time.sleep(5)
    print('Hello World!')

#新增功能
def timer(func):
    start_time = time.time()
    func()
    end_time = time.time()
    print(end_time - start_time)

timer(hw)

虽然最后的执行只用执行了新的函数即可,但是无法达到我们想要的效果,在执行hw()的情况下,就在原有功能上添加了计时的功能。

import time

#新增功能
def timer(func):
    def inner():
        start_time = time.time()
        func()
        end_time = time.time()
        print(end_time - start_time)
    return inner

#已有函数
def hw():
    time.sleep(5)
    print('Hello World!')

hw = timer(hw)
hw()

现在看起来代码已经可以实现我们的调用原有函数时候,在不修改原有函数的情况下,为其增加一些新功能了。但上面代码需要注意的是,17、18行代码关系较为复杂,且较为难看,因而还需要对其进行优化。

17、18行代码这里,可以看出在执行timer()的时候,timer()函数与内嵌函数inner()通过func变量形成一个闭包。17行代码中右边的timer(hw)是返回了inner的内存地址,并赋值给了变量hw;最终执行的hw()其实执行的是inner()函数。

import time

#新增功能
def timer(func):
    def inner():
        start_time = time.time()
        func()
        end_time = time.time()
        print(end_time - start_time)
    return inner

#已有函数
@timer  #语法糖
def hw():
    time.sleep(5)
    print('Hello World!')

hw()

这里只需加入#语法糖功能即可,标注该函数需要使用@timer函数来进行装饰即可。这样执行hw()就能实现功能的新增,并且没有改动过原有函数的一行代码。

0x02 装饰带参数与返回值的函数

前面写的需要被装饰的函数非常的简单,不需要参也没有返回值,因而需要考虑一下有返回值与参数的函数的装饰器如何书写。

import time

#新增功能
def timer(func):
    def inner(a):
        start_time = time.time()
        ret = func(a)
        end_time = time.time()
        print(end_time - start_time)
        return ret
    return inner

#已有函数
@timer  #语法糖
def hw(a):
    # time.sleep(5)
    print('Hello World!',a)
    return 'result'

print(hw(1))

对于参数的地方,只需在inner的地方加入参数即可,并用一个变量来接收原函数的返回值,最后通过装饰器在将其返回即可。

对于多参数的情况下,可以将参数写为*args,**kwargs。

0x03最终版装饰器写法

#装饰器
def wrapper(f):
    def inner(*args,**kwargs):
        pass    #新功能
        t = f()
        return t
    return inner

#原函数
@wrapper
def func(*args,**kwargs):
    pass
    return None

1 thought on “Python装饰器函数详解

  1. Google Chrome 69.0.3484.0 Google Chrome 69.0.3484.0 Windows 7 x64 Edition Windows 7 x64 Edition

    大佬,很厉害

发表评论