Python装饰器详解

共 4397字,需浏览 9分钟

 ·

2020-09-24 13:46


装饰器本质就是函数,作用是装饰其它函数,给其它函数增加附加功能,提高代码复用,减少代码量。

我们平时给函数增加新的功能时,通过修改此函数或在函数里调用新的函数实现,但是1、如果这个函数已经是上线的功能,这时修改程序原代码有很大风险  2、如果有100个这样的函数,我们就要找到100个地方进行修改。

例如:我们想新增功能,验证函数执行了多长时间,代码如下:

#修改原函数
import timedef sum1(): start = time.clock() sum = 1+2 print(sum) end = time.clock() print("time used:",end - start)sum1()
"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/Test/Test/test.py3time used: 2.9439962316848234e-05
Process finished with exit code 0

#原函数内调用新功能的函数import timedef sum1(): sum = 1+ 2 print (sum)def timeit(func): start = time.clock() func() end =time.clock() print("time used:", end - start)timeit(sum1)
"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/Test/Test/test.py3time used: 3.071996067845033e-05
Process finished with exit code 0


装饰器原则:

1、不能修改被装饰函数的源代码

2、不能修改被装饰函数的调用方式

实现装饰器储备知识:

高阶函数+嵌套函数=装饰器

1、函数即变量

def test1():    print('hello!')    return test1test2=test1test2()print(test2)
"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/Test/Test/test.pyhello!0x0000018E5D1A8F28>
Process finished with exit code 0

2、高阶函数

a:把一个函数名当做实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)

b:返回值中包含函数名

满足a或b就是高阶函数

def bar():    print('in the bar')def test1(func):    print(func)    func()    return test1test1(bar) #bar的内存地址+调用bar函数print(test1)#test1的内存地址print(test1(bar))#bar的内存地址+调用bar函数+test1的内存地址
"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/Test/Test/test.py0x0000026AC7C58F28>in the bar
0x0000026AC82C89D8>

0x0000026AC7C58F28>in the bar0x0000026AC82C89D8>
Process finished with exit code 0



import timedef bar(): time.sleep(3) print('in the bar')def test1(func): start_time=time.time() func() stop_time=time.time() print('the func run time is %s'%(stop_time-start_time)) return funcbar=test1(bar)bar()

"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/Test/Test/test.pyin the barthe func run time is 3.0008511543273926in the bar
Process finished with exit code 0

3、嵌套函数

def foo():    print('in the foo')    def bar():        print('in the bar')    bar()foo()
"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/Test/Test/test.pyin the fooin the bar
Process finished with exit code 0

不带参数的装饰器:

import timedef timer(func):    def deco():        start_time=time.time()        func()        stop_time=time.time()        print('the func run time is %s'%(stop_time-start_time))    return deco@timer    #test1=timer(test1)def test1():    time.sleep(3)    print('in the test1')test1()

"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/Test/Test/test.pyin the test1the func run time is 3.000833511352539
Process finished with exit code 0

带参数的装饰器:
从实:1中看出@timer相当于test2=timer(test2),timer(func)中func传的是test2,故func=test2
timer(test2)=deco,因为test2=timer(test2),故test2=deco=func
test2(name,age)=deco(name,age)=func(name,age)所以传参到deco和func里

实例1import timedef timer(func):    def deco(*args,**kwargs):        start_time=time.time()        func(*args,**kwargs)        stop_time=time.time()        print('the func run time is %s'%(stop_time-start_time))    return deco@timer #test1=timer(test1)def test1():    time.sleep(3)    print('in the test1')test1()@timer  #test2=timer(test2)def test2(name,age):    time.sleep(3)    print('%s %s in the test2'%(name,age))test2('wangli',22)
"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/Test/Test/test.pyin the test1the func run time is 3.0001492500305176wangli 22 in the test2the func run time is 3.000540256500244
Process finished with exit code 0


实例2
import time
def timmer(flag): """ :param flag: 接收装饰器的参数 :return: """ def outer_wrapper(func): """ :param func: 接收被装饰的函数 :return: """ # 接收被装饰函数的参数 def wrapper(*args, **kwargs): """
:param args: 收集被装饰函数的参数 :param kwargs: 收集被装饰函数的关键字参数 :return: """ if flag == "true": start_time = time.time() # 调用被装饰的函数 result = func(*args, **kwargs) # 让进程睡一秒 time.sleep(1) stop_time = time.time() print("{func} spend {time} ".format(func="add", time=stop_time - start_time)) return result else: print("Unexpected ending") return wrapper return outer_wrapper




浏览 28
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报