【python】python装饰器

为什么会用到装饰器?

功能与业务解耦+代码维护便利性

场景:统计函数执时间

import time
def cumulation():
    t1 = time.time()
    for i in range(0,10000):
        print(i * i) 
    t2 = time.time()
    print('Total Exec Time is {:.4}s'.format(t2 - t1))
View Code

如果有很多类似的函数需要计时,则需要每个函数里都加入同样的代码,冗杂、代码不清晰明了。

此时可以用到装饰器!

装饰器 --- 高阶函数+嵌套定义(原则:函数即变量)

def display_time(func):
    def wrapper():
        t1 = time.time()
        func()
        t2 = time.time()
        print('Total Exec Time {:.4}s'.format(t2 - t1))
        return t2-t1
    return wrapper
#语法糖
@display_time
def cumulation():
    for i in range(0,10000):
        print(i*i)

cumulation()
View Code

----------------------------------被修饰函数有返回值-----------------------------------

import time
def display_time(func):
    def wrapper():
        t1 = time.time()
        result = func()
        t2 = time.time()
        print('Total Exec Time {:.4}s'.format(t2-t1))
        return result
    return wrapper
#语法糖
@display_time
def cumulation():
    for i in range(0,10000):
        print(i*i)
    return i

a = cumulation()
View Code

----------------------------------被修饰函数带参-----------------------------------------

import time
def display_time(func):
    def wrapper(*args,**kwargs):
        t1 = time.time()
        result = func(*args,**kwargs)
        t2 = time.time()
        print('Total Exec Time {:.4}s'.format(t2-t1))
        return result
    return wrapper
#语法糖
@display_time
def cumulation(maxnum):
    for i in range(0,maxnum):
        print(i*i)
    return i

a = cumulation(10000)
View Code

----------------------------------装饰器带参-----------------------------------------------

import time
def log(text):
    def display_time(func):
        def wrapper(*args,**kwargs):
            t1 = time.time()
            result = func(*args,**kwargs)
            t2 = time.time()
            print('Total Exec Time {:.4}s'.format(t2-t1))
            print(text)
        return wrapper
    return display_time
#语法糖
@log('excute')
def cumulation(maxnum):
    for i in range(0,maxnum):
        print(i*i)
        
cumulation(10000)
View Code

------------------------------YouTube解释:清晰明了----------------------------------

def smart_div(func):
    def inner(a, b):
        if a > b:
            a, b = b, a
        return func(a,b)
    return inner


def div(a,b):
    print(a/b)

div = smart_div(div)

div(2,4)

 

 ---------------------------------------多个装饰器------------------------------------------

注意:装饰器只对函数进行装饰,装饰器不对装饰器进行装饰!!

装饰器顺序:

def out_1(func):
    print('i am out_1')
    def inner_1():
        print('i am inner_1')
        return func()
    return inner_1

def out_2(func):
    print('i am out_2')
    def inner_2():
        print('i am inner_2')
        return func()
    return inner_2

@out_1
@out_2
def func_print():
    print('i am func_print')

func_print()
View Code

输出结果如下:

    i am out_2

    i am out_1

    i am inner_1

    i am inner_2

    i am func_print

一句话这么理解:装饰器,只对函数进行装饰,装饰器不对装饰器进行装饰,所以

1~~~~out2先装饰func_print函数,相当于执行func_print = out_2(func_print),所以先打印了 i am out_2,

2~~~~@out_2装饰完之后,@out1再对func_print进行装饰,并且此时的func_print已经指向了inner_2函数,所以@out_1对他进行装饰相当于func_print= out1(inner_2)这个时候就会执行"i am out_1"的打印,

3~~~~此时的func_print就指向了inner_1,就是两个装饰都装饰完毕了,最后一行代码调用了func_print(),所以就相当于调用了inner_1,这个时候打印"i am inner_1"

4~~~~打印完成之后执行到inner_1里的return func() 此时的func是inner_2,再执行inner_2打印‘I am inner_2’,

5~~~~而inner_2里还有return fun(),这时的func才是最初的func_print,最后打印‘i am func_print’

以上描述看似复杂,但是你如果能理解这个黑体加粗的话,装饰器装饰顺序就是so easy!!!!!有木有

扩展:装饰器类型

python装饰器的4种类型:

函数装饰函数、函数装饰类、类装饰函数、类装饰类

1、函数装饰函数

  以上介绍的均为函数装饰函数,此处省略。

2、函数装饰类

 

3、类装饰函数

 

4、类装饰类

posted @ 2019-07-30 19:17  快乐happy园  阅读(87)  评论(0)    收藏  举报