装饰器

 需求1:需要大长脸写一个功能,测试一下同事二狗的函数的执行效率
import time #引入time模块
print(time.time())

def func1():
    time.sleep(1)
    print('来了,老弟')

def func2():
    time.sleep(1)
    print('回手 掏 ,走位走位....')
#
#
import time
start_time = time.time()
func1()
end_time = time.time()
print('此函数的执行时间是%s' % (end_time-start_time))

import time
start_time = time.time()
func2()
end_time = time.time()
print('此函数的执行时间是%s' % (end_time-start_time))

# 第一版本不好,重复造轮子,测试函数的效率 必须得复制代码测试 改版:

# 第二版 将脸哥的代码封装到函数中,基本完成,
import time

def func1():
    time.sleep(0.6)
    print('来了,老弟')

def func2():
    time.sleep(0.5)
    print('回手 掏 ,走位走位....')

def timmer(f):
    start_time = time.time()
    f()
    end_time = time.time()
    print('此函数的执行时间是%s' % (end_time-start_time))
timmer(func1)
timmer(func2)

# 第三版  领导要求在生产环境测试函数的真正的执行效率:线上500个函数
# 线上问题:
    # 线上的函数你不改变
    # 函数的原本的调用方式不能改变
import time
def func1():
    time.sleep(0.6)
    print('来了,老弟')

def func2():
    time.sleep(0.5)
    print('回手 掏 ,走位走位....')

# 原本线上的调用方式:
# func1()
# func2()

# 但是用了脸哥的测试效率的函数之后
def timmer(f):
    start_time = time.time()
    f()
    end_time = time.time()
    print('此函数的执行时间是%s' % (end_time-start_time))

# 此时你已经改变了原函数的调用方式,并且程序执行了两遍
func1()
timmer(func1)

# 第四版:第三版 没有改变函数里面的函数体,但是改变了函数的调用方法,所以要解决:用最少的代码,解决调用方式一致性的问题。
# 最终完成的需求 func1() 这个指令既要执行func1函数,又要测试效率
import time
def func1():
    time.sleep(0.6)
    print('来了,老弟')
#
# def func2():
#     time.sleep(0.5)
#     print('回手 掏 ,走位走位....')

def timmer(f): # f = func1 函数的内存地址
    def inner():
        start_time = time.time()
        f()
        end_time = time.time()
        print('此函数的执行时间是%s' % (end_time-start_time))
    return inner
func1 = timmer(func1) # = inner
func1()  # inner()

# 第五版: 最终基础版 python提供一个机制,优化,语法糖 @  上面还是不够优化,我们引入第5种python语法糖@   示例:func1 = timmer(func1) 就等于@timmer
import time
def timmer(f):  # f = func1 函数的内存地址
    def inner():
        start_time = time.time()
        f()
        end_time = time.time()
        print('此函数的执行时间是%s' % (end_time - start_time))

    return inner

@timmer # func1 = timmer(func1)
def func1():
    time.sleep(0.6)
    print('来了,老弟')

func1()  # inner()
@timmer
def func2():
    time.sleep(0.6)
    print('来le')
func2()

@timmer
def func3():
    time.sleep(0.6)
    print('')
func3()

二、被装饰函数带参数

import time
def timmer(f):  # f = func1或者func2 函数的内存地址
    def inner(*args, **kwargs):
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        print('此函数的执行时间是%s' % (end_time - start_time))

    return inner

@timmer # func1 = timmer(func1) 在某个函数的上面加上这个
def func1(a):
    time.sleep(0.6)
    print('来了,%s' % (a))
func1('alex')

@timmer  # func2 = timmer(func2)
def func2(c,d):
    time.sleep(0.6)
    print('%s 年龄 %s' % (c,d))
func2('二狗',21)

三、被装饰函数带返回值

import time
def timmer(f):  # f = func1 函数的内存地址
    def inner(*args, **kwargs):
        start_time = time.time()
        ret = f(*args, **kwargs)
        end_time = time.time()
        print('此函数的执行时间是%s' % (end_time - start_time))
        return ret

    return inner
@timmer  # func1 = timmer(func1)
def func1(a):
    time.sleep(0.6)
    print('来了,%s' % (a))
    return 666
print(func1('alex'))  # print(inner('alex'))

总结:

1、装饰器本质其实闭包,
2、装饰器在不改变原函数的内部函数体以及调用方式的前提下,给函数增加了额外的功能:登录,注册,打印日志,函数效率等等。

四、手写装饰器

# 手写装饰器1,先写闭包:
def wrapper(f):
    def inner():
        f()
    return inner

# 手写装饰器2,增加参数:
def wrapper(f):
    def inner(*args,**kwargs):
        f(*args,**kwargs)
    return inner
# 手写装饰器3,增加返回值ret,增加函数部分:

def wrapper(f): def inner(*args, **kwargs): ''' 执行被装饰的函数之前的操作''' print('执行之前', 555) #示例 ret = f(*args, **kwargs) print('执行之后', 666) #示例 ''' 执行被装饰的函数之后的操作''' return ret return inner @wrapper def func1(): pass func1()

原文地址:https://www.cnblogs.com/wangkaiok/p/9906830.html