装饰器函数
导航
装饰器的形成过程
装饰器的功能了解
importtimedeffunc1():print("in func1")deftimer(func):definner():
start=time.time()
func()print(time.time()-start)returninner
func1=timer(func1)
func1()'''timer(func1)() --> 即执行的是 inner()
输出:
in func1
0.0'''
装饰器 - 简单版
需要在目标的执行函数上加一次赋值调用。
装饰器的语法糖
deftimer(func):definner():
start=time.time()
func()print(time.time() -start)returninner
@timerdef func1(): #==> func1 = timer(func1)
print("in func1")
func1()
装饰器 - 语法糖
总结
装饰器的本质:一个闭包函数
装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展
装饰一个带参数的函数
deftimer(func):def inner(a): ###
start =time.time()
func(a)###
print(time.time() -start)returninner
@timerdef func1(a): ###
print("in func1" +a)
func1("hello world")
被装饰函数需要传参
不同函数需要不同的参数,但又需要同一个功能的装饰器。
ef timer(func):def inner(*args, **kwargs):print("函数开始执行")
func(*args, **kwargs)print("函数执行结束")returninner
@timerdeffunc1(name):print("..." +name)
@timerdeffunc2(age):print("年龄:",age)
func1("Clare")
func2(18)'''函数开始执行
...Clare
函数执行结束
函数开始执行
年龄: 18
函数执行结束'''
一次性hold住所有函数传参
带返回值的装饰器
deftimer(func):def inner(*args, **kwargs):
ret= func(*args, **kwargs)return ret ###
returninner
@timerdeffunc1(name):return "姓名:%s" %name
res= func1("Clare")print(res)'''姓名:Clare'''
被装饰函数有返回值
查看函数信息的方法失效及问题解决
deftimer(func):def inner(*args, **kwargs):
ret= func(*args, **kwargs)returnretreturninner
@timerdeffunc1():'''这是一个func1'''
return "in func1"
print(func1.__doc__) #查看函数注释:None
print(func1.__name__) #inner,执行func1实际是执行:timer(func1)(),即inner()
############# 对比 #############
deffunc2():'''这是一个func1'''
return "in func1"
print(func2.__doc__) #查看函数注释:"这是一个func1"
print(func2.__name__) #func2
查看函数信息的方法失效
from functools importwrapsdeftimer(func):
@wraps(func)def inner(*args, **kwargs):
ret= func(*args, **kwargs)returnretreturninner
@timerdeffunc1():'''这是一个func1'''
return "in func1"
print(func1.__doc__) #这是一个func1
print(func1.__name__) #func1
解决方法:@wraps(func)
装饰器的主要功能和固定结构
装饰器的主要功能
在不改变函数调用方式的基础上在函数的前、后添加功能。
装饰器的固定结构
defwrapper(func):def inner(*args, **kwargs):'''执行函数之前要进行的操作'''ret= func(*args, **kwargs)'''执行函数之后要进行的操作'''
returnretreturn inner
from functools importwrapsdefwrapper(func):
@wraps(func)#最内层函数上方
def inner(*args, **kwargs):
ret= func(*args, **kwargs)returnretreturn inner
wraps(func) 固定结构
带参数的装饰器
如果说很多个函数共同使用了一个装饰器,现需要取消掉装饰器的功能。万一去掉之后又需要加上,工作量太过繁重。
或者说某几个函数仍需要该装饰器,而另外几个函数暂时性的不需要呢。
defouter(flag):defwrapper(func):def inner(*args, **kwargs):ifflag:print('''执行函数之前要进行的操作''')
ret= func(*args, **kwargs)ifflag:print('''执行函数之后要进行的操作''')returnretreturninnerreturnwrapper############## 不需要被装饰 ###########
@outer(False)deffunc():print("in func")
func()#in func
############## 需要被装饰 ###########
@outer(True)deffunc():print("in func")
func()'''执行函数之前要进行的操作
in func
执行函数之后要进行的操作'''
控制函数是否需要被装饰
多个装饰器装饰同一个函数
defwrapper1(func):def inner(*args, **kwargs):print("wrapper1")
ret= func(*args, **kwargs)print("wrapper1")returnretreturninnerdefwrapper2(func):def inner(*args, **kwargs):print("wrapper2")
ret= func(*args, **kwargs)print("wrapper2")returnretreturninner
@wrapper2#func1 = wrapper2(wrapper1(func))
@wrapper1 #func1 = wrapper1(func)
deffunc():print("func")
func()'''wrapper2
wrapper1
func
wrapper1
wrapper2'''
多个装饰器装饰同一个函数的执行顺序
一个装饰器时可以简写为return func(*args, **kwargs)
多个装饰器时,不能简写,不会执行return后的代码
ret= func(*args, **kwargs)return ret
注意
#####################################
一、解耦
要完成一个完整的功能,但这个功能的规模要尽可能小,并且和这个功能无关的其他代码应该和这个函数分离
# 1、增强代码的可读性
# 2、减少代码变更的重复影响
1 deffunc():2 whileTrue:3 print("从前有座山,山里有座庙,庙里有个老和尚在讲故事,故事是这样的:")4
5 func()
# 运行结果:会无休止的打印该字符串,没有结束。
1 deffunc():2 print("从前有座山,山里有座庙,庙里有个老和尚在讲故事,故事是这样的:")3
4 for i in range(10):5 func()#打印该字符串十次。修改range里的数值可控制打印次数。
二、递归
什么是递归:
# 1、一个函数在自己内部调用自己。
# 2、递归的层数在python里是有限制的。(997/998层)