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