Python全栈--Day11 装饰器

一. 装饰器

1. 装饰器的本质就是一个Python函数, 它可以让其他函数在不需要任何代码变动的前提下, 增加额外的功能. 装饰器的返回值也是一个函数对象. 

2. 装饰器的应用场景: 如插入日志, 性能测试, 事物处理, 缓存等等

3. 装饰器的形成过程

  第一步: 有一个需求, 要在不改变函数代码的情况下, 测试一个函数的执行时间

import time

def func():
    start_time = time.time()
    time.sleep(1)  # 睡一秒, 模拟程序执行时间
    end_time = time.time()
    print(end_time - start_time)

func()

输出: 1.0002674890518188

  第二步: 我有很多函数要测试, 那么不可能每一次都单独写个测试功能, 那么将第一步的功能封装成一个函数, 将要测试运行时间的函数作为参数传入, 今后要用直接调用就行了

import time

# 待测试的函数
def func():
    time.sleep(1)
# 测试运行时间功能
def timmer(f):
    start_time = time.time()
    f()  # 待测试函数执行
    end_time = time.time()
    print(end_time-start_time)
timmer(func)

输出: 1.0006756782531738

  第三步: 假设我有100个函数都要测试, 那么每个函数测试时都要写timmer(func), 太麻烦了, 且函数的调用方式也改变了, 那么现在做第三步

import time

# 待装饰函数
def func():
    time.sleep(1)

# 装饰器
def timmer(f):

    def inner():
        start_time = time.time()
        f()  # 待测试函数执行
        end_time = time.time()
        print(end_time-start_time)
    return inner

func = timmer(func)  # 先执行timmer(func), 将inner返回给func
func() # 实际是inner()

输出: 1.0006918907165527

  第四步: 经过第三步的处理, 已经将函数的调用方式改为了func(), 但还是要写func = timmer(func). 为此, 引入语法糖: @装饰器名

import time
# 装饰器
def timmer(f):

    def inner():
        start_time = time.time()
        f()  # 待测试函数执行
        end_time = time.time()
        print(end_time-start_time)
    return inner
@timmer
def func():
    time.sleep(1)
func()
输出: 1.0006766319274902

二. 装饰带返回值函数的装饰器

  经过第一部分的四步, 已经制作了一个不带返回值得装饰器, 如果要做一个带返回值得装饰器, 那么做出如下配置

import time

# 装饰器
def timmer(f):

    def inner():
        start_time = time.time()
        ret = f()  # 待测试函数执行, 且将返回值赋给ret
        end_time = time.time()
        print(end_time-start_time)
        return ret
    return inner

@timmer
def func():
    time.sleep(1)
    return '我是带返回值的函数, 我有装饰器了!!!'

dsb = func()
print(dsb)

输出:

 1.0006749629974365
 我是带返回值的函数, 我有装饰器了!!!

 三. 装饰带参数函数的装饰器

1. 固定的参数

import time

# 装饰器
def timmer(f):

    def inner(a):
        start_time = time.time()
        ret = f(a)  # 待测试函数执行, 且将返回值赋给ret
        end_time = time.time()
        print(end_time-start_time)
        return ret
    return inner

@timmer
def func(a):
    time.sleep(1)
    print('我是参数a:', a)
    return '我是带参数且有返回值的函数, 我有装饰器了!!!'

dsb = func("牛批")
print(dsb)

输出:
我是参数a: 牛批
1.0006965621974372
我是带参数且有返回值的函数, 我有装饰器了!!!

2. 动态参数

import time

# 装饰器
def timmer(f):

    def inner(*args, **kwargs): # 动态参数
        start_time = time.time()
        ret = f(*args, **kwargs)  
        end_time = time.time()
        print(end_time-start_time)
        return ret
    return inner

@timmer
def func(a):
    time.sleep(1)
    print('我是动态参数, 随便传')
    return '我是动态参数且有返回值的函数, 我TM也有装饰器了!!!'

dsb = func("牛批")
print(dsb)

输出:
我是动态参数, 随便传
1.0006752014160156
我是动态参数且有返回值的函数, 我TM也有装饰器了

四. 装饰器的固定格式

# 装饰器
def wrapper(f):  # f是被装饰的函数

    def inner(*args, **krargs)  # 动态参数

        你想干嘛?
        ret = f(*args, **kwargs)  # 被装饰的函数执行

        你还想干嘛?

        return ret
  return inner # 注意这里不能加() @wrapper
# 语法糖 def 被装饰函数(): ... return '我是被装饰函数'

猜你喜欢

转载自www.cnblogs.com/python-web/p/9652934.html