Python装饰器详解
装饰器本质就是函数,作用是装饰其它函数,给其它函数增加附加功能,提高代码复用,减少代码量。
我们平时给函数增加新的功能时,通过修改此函数或在函数里调用新的函数实现,但是1、如果这个函数已经是上线的功能,这时修改程序原代码有很大风险 2、如果有100个这样的函数,我们就要找到100个地方进行修改。
例如:我们想新增功能,验证函数执行了多长时间,代码如下:
#修改原函数
import time
def 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.py
3
time used: 2.9439962316848234e-05
Process finished with exit code 0
#原函数内调用新功能的函数
import time
def 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.py
3
time used: 3.071996067845033e-05
Process finished with exit code 0
装饰器原则:
1、不能修改被装饰函数的源代码
2、不能修改被装饰函数的调用方式
实现装饰器储备知识:
高阶函数+嵌套函数=装饰器
1、函数即变量
def test1():
print('hello!')
return test1
test2=test1
test2()
print(test2)
"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/Test/Test/test.py
hello!
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 test1
test1(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.py
0x0000026AC7C58F28 >in the bar
0x0000026AC82C89D8 >
0x0000026AC7C58F28 >in the bar
0x0000026AC82C89D8 >
Process finished with exit code 0
import time
def 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 func
bar=test1(bar)
bar()
"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/Test/Test/test.py
in the bar
the func run time is 3.0008511543273926
in 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.py
in the foo
in the bar
Process finished with exit code 0
不带参数的装饰器:
import time
def 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
def test1():
time.sleep(3)
print('in the test1')
test1()
"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/Test/Test/test.py
in the test1
the 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里
实例1:
import time
def 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
def test1():
time.sleep(3)
print('in the test1')
test1()
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.py
in the test1
the func run time is 3.0001492500305176
wangli 22 in the test2
the 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
评论