之前写过一篇关于装饰器的文章,但是感觉写的不太好,就想着再写一篇
装饰器本质就是函数,功能是为其他函数添加附加功能
原则:
1、不修改被修饰函数的源代码
2、不修改被修饰函数的调用方式
还是从需求开始,一个函数,需要知道这个函数的运行时间
#计算从1到100的和
def cal(l):
sum = 0
for i in l:
sum+=i
return sum
print(cal(range(101)))
#算出来这个函数执行的时间
import time
def cal(l):
s_time = time.time()
time.sleep(1)
sum = 0
for i in l:
sum+=i
e_time = time.time()
print('运行的实时间是%s'%(e_time-s_time))
return sum
print(cal(range(101)))
def test1():
pass
def test2():
pass
#如果很多个函数都要增加这个统计时间的功能,那么一个个加不仅麻烦而且还改变了源代码
def foo():
print('nihao')
def test(func):
print(func)
start_tiem = time.time()
time.sleep(1)
func()
stop_time = time.time()
print('运行的实时间是%s' % (stop_time - start_tiem))
test(foo)
#这样没有修改源代码,但是修改了函数的调用方式,原来调用foo(),现在是test(foo)
#不修改foo源代码,不修改调用方式
import time
def foo():
time.sleep(1)
print('nihao')
def test(func):
start_tiem = time.time()
func()
stop_time = time.time()
print('运行的实时间是%s' % (stop_time - start_tiem))
return func
res= test(foo)
res()
#可以赋值给foo()
foo = test(foo)
foo()
##这个函数多运行了一次,所以不行
#下面用函数嵌套,函数里面嵌套函数
def father(name):
print('来自爸爸%s'%name)
def son():
name = '321'
print('来自儿子%s'%name)
son()
#print(locals())#打印当前层的局部变量
father('123')
#son是一个包,外面的father是另外一个包;son里面封装了一个变量,father封装了一个函数,函数即变量,闭包的概念和作用域差不多
#装饰器= 高阶函数+函数嵌套+闭包 写一个架子,满足装饰器的要求
#这个就是装饰器的架子
import time
def time1(func):
def warpper():
#print(func)
start_tiem = time.time()
func()
stop_time = time.time()
print('运行的实时间是%s' % (stop_time - start_tiem))
return warpper
def test():
time.sleep(3)
print('结束')
res = time1(test)#这个返回的是wrapper的内存地址
res()#这个只想的wrapper()这个函数,反馈到上面就是在只想test()这个函数
test = time1(test)#这个返回的是wrapper的内存地址
test()#这个只想的wrapper()这个函数,反馈到上面就是在只想test()这个函数
#这个好像已经好了,没有改变调用方式,没有改变源代码,并且执行结果反馈正确,但是每次调用都要定义变量赋值
#怎么解决 @time1相当于test = time1(test) 这个步骤
import time
def time1(func):
def warpper():
#print(func)
start_tiem = time.time()
func()
stop_time = time.time()
print('运行的实时间是%s' % (stop_time - start_tiem))
return warpper
@time1#test = time1(test)
def test():
time.sleep(3)
print('结束')
return '这是我要的返回值'
res= test()
print(res)#打印结果是None,为什么不是'这是我要的返回值' ,因为加了@time1,
# 运行test()等于运行了warpper(),而这个函数的返回值是NOne,所以。。。
#那怎么才能返回正确的结果呢,这个结果呢,请看大屏幕
def time1(func):
def warpper():
#print(func)
start_tiem = time.time()
res = func()#这个地方只需要把func()赋值给res,然后在后面返回res就能解决
stop_time = time.time()
print('运行的实时间是%s' % (stop_time - start_tiem))
return res
return warpper
@time1#test = time1(test)
def test():
time.sleep(3)
print('结束')
return '这是我要的返回值'
res= test()
print(res)
import time
#需求在test中增加参数,并且改完之后还要加很多参数怎么解决
def time1(func):
def warpper(*args,**kwargs):
#print(func)
start_tiem = time.time()
res = func(*args,**kwargs)#之所以这个地方也加*,是因为test()中传什么参数,在这个地方可以解析为什么参数,原封不动
#因为func()这个函数就是test()这个函数,所以传的参数要和test()函数中的参数一致
stop_time = time.time()
print('运行的实时间是%s' % (stop_time - start_tiem))
return res
return warpper
@time1#test = time1(test)
def test(name,age):
time.sleep(3)
print('结束,名字是%s,年龄是%s'%(name,age))
return '这是我要的返回值'
res= test()
print(res)