@***装饰器(python)

0 前言:

在阅读代码中,发现@***的什么的,原来这个就是大名鼎鼎的装饰器,然后就学习了下装饰器,记录下学习心得。

1 装饰器介绍:

python装饰器就是用于拓展原来函数功能的一种特殊的函数,特殊之处在于它返回的是一个函数。

优点:不用更改原代码前提下可以新增函数的功能。

应用场景:插入日志,性能测试,事务处理,提取大量函数中与本身功能无关的类似代码,达到代码重复使用的目的。

2 装饰器简单应用

用例子说明事物是最好懂的。

首先亮出原代码

import time 
def func():
    print("hello")
    time.sleep(1)
    print("tian")

要求:记录函数的执行总时间

常规想法:更改原代码。

import time
def func():
    startTime = time.time()

    print("hello")
    time.sleep(1)
    print("tian")
    endTime = time.time()

    msecs = (endTime - startTime)*1000
    print("time is %d ms" %msecs)

思考:如果使用装饰器呢?琢磨下面的代码就很好理解了。

import  time
def decorator(fun):
    def wrapper():
        startTime = time.time()
        fun()
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
    return wrapper
@decorator
def fun():
    print("hello")
    time.sleep(1)
    print("tian")
if __name__=="__main__":
    f=fun
    f()

3 装饰器高级应用 

3.1 带参数的装饰器

import time
def decorator(fun):
    def wrapper(a,b):
        startTime=time.time()
        fun(a,b)
        endTime=time.time()
        msecs=(endTime - startTime)*1000

        print("time is %d ms" %msecs)
    return wrapper
@decorator
def fun(a,b):
    print("hello")
    time.sleep(1)
    print("result is %d" %(a+b))
if __name__=="__main__":
    f=fun
    f(3,4)

3.2 带有不定参数的装饰器

以*开头,可以传多个参数,**是形参中按照关键字传值把多余的传值以字典的方式呈现。

*args:表示将实参中按照位置传值,多出来的值都给args,且以元祖的方式呈现。

**kwargs:表示形参中按照关键字传值把多余的传值以字典的形式呈现

import time
def decorator(fun):
    def wrapper(*args,**kwargs):
        startTime=time.time()
        fun(*args,**kwargs)
        endTime=time.time()
        msecs=(endTime - startTime)*1000
        print("time is %d ms" %msecs)
    return wrapper
@decorator
def fun1(a,b):
    print("hello")
    time.sleep(1)
    print("result is %d" %(a+b))
@decorator
def fun2(a,b,c):
    print("hello")
    time.sleep(1)
    print("result is %d" %(a+b+c))

if __name__=="__main__":
    fun1(3,4)
    fun2(3,4,5)

3.3 多个装饰器

#多个装饰器
import time
def deco01(func):
    def wrapper(*args, **kwargs):
        print("this is deco01")
        startTime = time.time()
        func(*args, **kwargs)
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
        print("deco01 end here")
    return wrapper
def deco02(func):
    def wrapper(*args, **kwargs):
        print("this is deco02")
        func(*args, **kwargs)

        print("deco02 end here")
    return wrapper
@deco01
@deco02
def func(a,b):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b))
if __name__ == '__main__':
    f = func
    f(3,4)

输出结果:

this is deco01
this is deco02
hello,here is a func for add :
result is 7
deco02 end here
time is 1000 ms
deco01 end here

Process finished with exit code 0

观察输出顺序可以大概推断执行的顺序。多个装饰器执行的顺序就是从最后一个装饰器开始,执行到第一个装饰器,再执行函数本身。


4 参考

1 https://blog.csdn.net/xiangxianghehe/article/details/77170585

2 http://python.jobbole.com/82344/

3 https://www.cnblogs.com/xuyuanyuan123/p/6674645.html

 

你可能感兴趣的:(python)