08_Python装饰器函数_全栈开发学习笔记

1. 装饰器开篇_time模块

范例1:
time.sleep():让程序在执行到这个位置的时候停一会儿

import time

time.sleep(5)
print("哇咔咔")

执行结果:

# 先停5秒
哇咔咔


范例2:
time.time():获取当前时间(从1970年到现在的总秒数)

import time

print(time.time())

执行结果:

1539995896.847099


范例3:
统计代码执行的时间

import time

def func():
    start = time.time()
    print("世界大同")
    time.sleep(0.01)
    end = time.time()
    print(end-start)
func()

执行结果

世界大同
0.010123491287231445


范例4.1:
将范例3函数内的时间与打印分开,各自独立成一个函数

import time

def timer(f):    # 计算函数执行的时间
    start = time.time()
    f()
    end = time.time()
    print(end-start)

def func():
    time.sleep(0.01)
    print("世界大同")

timer(func)

执行结果

世界大同
0.010216474533081055


范例4.2:
同范例4.1,容易理解的方式

import time

def func():
    time.sleep(0.01)
    print("世界大同")

def timer():
    start = time.time()
    func()
    end = time.time()
    print(end-start)

timer()

执行结果:

世界大同
0.010337352752685547


范例5:
进一步优化范例4

import time

def func():    # 第一步
    time.sleep(0.01)    # 第十步
    print("世界大同")    # 第十一步

def timer(f):    # 第二步:f为func的内存地址    # 装饰器函数
    def inner():    # 第四步
        start = time.time()    # 第八步
        f()    # 第九步 # 被装饰的函数
        end = time.time()    # 第十二步
        print(end-start)    # 第十三步
    return inner    # 第五步

func = timer(func)    # 第三步:等号右边    # 第六步:等号左边
func()    # 第七步:执行inner()

执行结果

世界大同
0.01023554801940918


1.1 装饰器的作用

装饰器的作用 —— 不想修改函数的调用方式 但是还想在原来的函数前后添加功能
timmer就是一个装饰器函数,只是对一个函数有一些装饰作用。


2 语法糖

import time

def timer(f):    # 装饰器函数
    def inner():
        start = time.time()
        f()    # 被装饰的函数
        end = time.time()
        print(end-start)
    return inner

@timer    # 语法糖  @装饰器函数名
def func():    # 被装饰的函数
    time.sleep(0.01)
    print("世界大同")

#func = timer(func)    # 被语法糖代替
func()

执行结果

世界大同
0.010994911193847656

3 取得被装饰函数的返回值

import time

def timer(f):    # 装饰器函数
    def inner():
        start = time.time()
        ret = f()    # 被装饰的函数
        end = time.time()
        print(end-start)
        return ret
    return inner

@timer    # 语法糖
def func():
    time.sleep(0.01)
    print("世界大同")
    return "新年好"

#func = timer(func)    # 被语法糖代替
ret = func()
print(ret)

执行结果

世界大同
0.010995149612426758
新年好

4 装饰带一个参数函数的装饰器

范例:

import time

def timer(f):    # 装饰器函数
    def inner(a):
        start = time.time()
        ret = f(a)    # 被装饰的函数
        end = time.time()
        print(end-start)
        return ret
    return inner

@timer    # 语法糖
def func(a):
    time.sleep(0.01)
    print("世界大同",a)
    return "新年好"

#func = timer(func)    # 被语法糖代替
ret = func(1)
print(ret)

执行结果

世界大同 1
0.010066032409667969
新年好

5 装饰带万能参数函数的装饰器

范例:

import time

def timer(f):    # 装饰器函数
    def inner(*args,**kwargs):
        start = time.time()
        ret = f(*args,**kwargs)    # 被装饰的函数
        end = time.time()
        print(end-start)
        return ret
    return inner

@timer    # 语法糖
def func(a,b):
    time.sleep(0.01)
    print("世界大同",a,b)
    return "新年好"

@timer    # 语法糖
def func1(a):
    time.sleep(0.01)
    print("世界大同",a)
    return "新年好"

#func = timer(func)    # 被语法糖代替
ret = func(1,2)
ret = func(1,b = 2)
print(ret)

执行结果

世界大同 1 2
0.010993003845214844
世界大同 1 2
0.010015010833740234
新年好

6 装饰器的固定格式

详解:

def wrapper(f):    #装饰器函数,f是被装饰的函数
    def inner(*args,**kwargs):
        '''在被装饰函数之前要做的事'''
        ret = f(*args,**kwargs)    #被装饰的函数
        '''在被装饰函数之后要做的事'''
        return ret
    return inner

@wrapper         #语法糖 @装饰器函数名
def func(a,b):     #被装饰的函数
    time.sleep(0.01)
    print('老板好同事好大家好',a,b)
    return '新年好'


粗解:

def wrapper(func):   #qqxing
    def inner(*args,**kwargs):
        ret = func(*args,**kwargs)   #被装饰的函数
        return ret
    return inner

@wrapper        #qqxing = wrapper(qqxing)
def qqxing():
    print(123)

ret = qqxing()   #inner


复习时的例子:

def wrapper(func):    # 第一步
    def inner(*args,**kwargs):    # 第三步
        print('在被装饰的函数执行之前做的事')    # 第七步
        ret = func(*args,**kwargs)# 第八步 等号右边:holiday(*(3),**{})    # 第十一步:等号左边,接收了第十步的返回值
        print('在被装饰的函数执行之后做的事')    # 第十二步
        return ret    # 第十三步
    return inner    # 第四步

@wrapper   #holiday = wrapper(holiday)    # 第二步:执行等号右边    # 第五步:等号左边,此时的holiday就等于inner
def holiday(day):
    print('全体放假%s天'%day)    # 第九步
    return '好开心'    # 第十步

ret = holiday(3)    # 第六步:等号右边 inner(3)    # 第十四步,接收第十三步的返回值
print(ret)    # 第十五步

执行结果:

在被装饰的函数执行之前做的事
全体放假3天
好开心
在被装饰的函数执行之后做的事


另一个说明:

def outer(*args):    # 接收 聚合
    print(args)
    print(*args)    # 调用 打散
    def inner(*args):    # 接收 聚合
        print('inner : ',args)
    inner(*args)    # 调用 打散


outer(1,2,3,4)   #==outer(*[1,2,3,4])  #==outer(*(1,2,3,4))

7 查看函数信息的方法

7.1 查看字符串格式的函数名

范例:_name_

def wahaha():
    print("哇咔咔")

print(wahaha.__name__)

执行结果

wahaha


7.2 查看函数内的注释文档

范例:_doc_

def wahaha():
    """
    一个打印哇哈哈的函数
    :return:
    """
    print("哇咔咔")

print(wahaha.__doc__)

执行结果

    一个打印哇哈哈的函数
    :return:


7.3 装饰器:wraps

@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。

范例1:未使用@wraps

#from functools import wraps

def wrapper(func):  #func = holiday
    #@wraps(func)
    def inner(*args,**kwargs):
        print('在被装饰的函数执行之前做的事')
        ret = func(*args,**kwargs)
        print('在被装饰的函数执行之后做的事')
        return ret
    return inner

@wrapper   #holiday = wrapper(holiday)
def holiday(day):
    '''这是一个放假通知'''
    print('全体放假%s天'%day)
    return '好开心'

print(holiday.__name__)

执行结果

inner


范例2:使用@wraps

from functools import wraps

def wrapper(func):  #func = holiday
    @wraps(func)    # 加在最内层函数正上方
    def inner(*args,**kwargs):
        print('在被装饰的函数执行之前做的事')
        ret = func(*args,**kwargs)
        print('在被装饰的函数执行之后做的事')
        return ret
    return inner

@wrapper   #holiday = wrapper(holiday)
def holiday(day):
    '''这是一个放假通知'''
    print('全体放假%s天'%day)
    return '好开心'

print(holiday.__name__)
print(holiday.__doc__)

ret = holiday(3)   #inner
print(ret)

执行结果

holiday
这是一个放假通知

在被装饰的函数执行之前做的事
全体放假3天
在被装饰的函数执行之后做的事
好开心

8 带参数的装饰器(三层函数)

范例1.1:给装饰器一个控制开关(开)

import time
FLAGE = True
def timmer_out(flag):
    def timmer(func):
        def inner(*args,**kwargs):
            if flag:
                start = time.time()
                ret = func(*args,**kwargs)
                end = time.time()
                print(end-start)
                return ret
            else:
                ret = func(*args, **kwargs)
                return ret
        return inner
    return timmer

# 第二种理解 timmer = timmer_out(FLAGE)
@timmer_out(FLAGE)    # 第一种理解 timmer_out(FLAG) == timmer    @timmer == wahaha = timmer(wahaha)
def wahaha():
    time.sleep(0.1)
    print('wahahahahahaha')

@timmer_out(FLAGE)
def erguotou():
    time.sleep(0.1)
    print('erguotoutoutou')

wahaha()
erguotou()

执行结果:

wahahahahahaha
0.10094094276428223
erguotoutoutou
0.10099601745605469


范例1.2:给装饰器一个控制开关(关)

# 关
import time
FLAGE = False
def timmer_out(flag):
    def timmer(func):
        def inner(*args,**kwargs):
            if flag:
                start = time.time()
                ret = func(*args,**kwargs)
                end = time.time()
                print(end-start)
                return ret
            else:
                ret = func(*args, **kwargs)
                return ret
        return inner
    return timmer

# timmer = timmer_out(FLAGE)
@timmer_out(FLAGE)
def wahaha():
    time.sleep(0.1)
    print('wahahahahahaha')

@timmer_out(FLAGE)
def erguotou():
    time.sleep(0.1)
    print('erguotoutoutou')

wahaha()
erguotou()

执行结果:

wahahahahahaha
erguotoutoutou

9 多个装饰器装饰一个函数

双层装饰器可用于:
1.1 记录用户的登录情况
1.2 计算这个函数的执行时间

范例1.1:双层装饰器1

def wrapper1(func):    # 第一步    # 第三之后 func -> f
    def inner1():    # 第四步
        print('wrapper1 ,before func')    # 第十五步    # 第二执行
        func()    # 第十六步  f()
        print('wrapper1 ,after func')    # 第十八步    # 第四执行
    return inner1    # 第五步

def wrapper2(func):    # 第二步    # 第七步之后 func --> inner1
    def inner2():    # 第八步
        print('wrapper2 ,before func')    # 第十三步    # 第一执行
        func()    # 第十四步  inner1()
        print('wrapper2 ,after func')    # 第十九部    # 第五执行
    return inner2    # 第九步

@wrapper2    # 第七步 f = wrapper2(f) wrapper(inner1)    # 第十步 f = wrapper2(f) wrapper(inner1) = inner2
@wrapper1    # 第三步 f = wrapper1(f)    # 第六步 f = wrapper1(f) = inner1
def f():
    print('in f')    # 第十七步    # 第三执行

f()    # 第十一步 执行了inner2()

执行结果

wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func


范例1.2:双层装饰器2

def wrapper1(func):
    def inner1():
        print('wrapper1 ,before func')   # 第一执行
        func()
        print('wrapper1 ,after func')   # 第五执行
    return inner1

def wrapper2(func):
    def inner2():
        print('wrapper2 ,before func')   # 第二执行
        func()
        print('wrapper2 ,after func')   # 第四执行
    return inner2

@wrapper1
@wrapper2
def f():
    print('in f')   # 第三执行

f()

执行结果:

wrapper1 ,before func
wrapper2 ,before func
in f
wrapper2 ,after func
wrapper1 ,after func


范例2:三层装饰器

def wrapper1(func):
    def inner1():
        print('wrapper1 ,before func')
        ret = func()
        print('wrapper1 ,after func')
        return ret
    return inner1

def wrapper2(func):
    def inner2():
        print('wrapper2 ,before func')
        ret = func()
        print('wrapper2 ,after func')
        return ret
    return inner2

def wrapper3(func):
    def inner3():
        print('wrapper3 ,before func')
        ret = func()
        print('wrapper3 ,after func')
        return ret
    return inner3

@wrapper3
@wrapper2
@wrapper1   # f = wra
def f():
    print('in f')
    return '哈哈哈'
print(f())

执行结果

wrapper3 ,before func
wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func
wrapper3 ,after func
哈哈哈

你可能感兴趣的:(08_Python装饰器函数_全栈开发学习笔记)