装饰器
什么是装饰器
首先我们要明确 装饰器是一个函数,应该是叫做装饰器函数,简称为装饰器,这个函数遵守开闭原则,在不修改原函数的基础上对该函数进行功能的扩展
装饰器的作用
不想修改函数的调用方式 但是还想在原来的函数前后添加功能
主要功能
在不改变函数调用方式的基础上在函数的前、后添加功能
装饰器的形成过程
有一个需求:计算一个已有的函数的运行时间。
(time模块,用于操作时间,下面用到的time.time是获取当前时间戳,这个时间戳是从1970年1月1日0点0分开始计算到现在的秒数。time.sleep() 程序暂停多少秒)
import time
def func1():
print('in func1')
time.sleep(1)
def timer(func):
def inner():
start = time.time()
func()
print(time.time() - start)
return inner
func1 = timer(func1)
func1()
这个程序的运行过程:
@语法糖
import time
def timer(func):
def inner():
start = time.time()
func()
print(time.time() - start)
return inner
@timer #==> func1 = timer(func1) #语法糖 @装饰器函数名
def 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(a)
func1(1)
成功hold住所有函数传参
import time
def timer(func):
def inner(*args,**kwargs):
start = time.time()
re = func(*args,**kwargs)
print(time.time() - start)
return re
return inner
@timer #==> func1 = timer(func1)
def func1(a,b):
print('in func1')
@timer #==> func2 = timer(func2)
def func2(a):
print('in func2 and get a:%s'%(a))
return 'fun2 over'
func1('aaaaaa','bbbbbb')
print(func2('aaaaaa'))
带返回值的装饰器
import time
def timer(func):
def inner(*args,**kwargs):
start = time.time()
re = func(*args,**kwargs)
print(time.time() - start)
return re
return inner
@timer #==> func2 = timer(func2)
def func2(a):
print('in func2 and get a:%s'%(a))
return 'fun2 over'
func2('aaaaaa','bbbbbb')
print(func2('aaaaaa'))
装饰器的固定格式:
def timer(func):
def inner(*args,**kwargs):
'''执行函数之前要做的'''
re = func(*args,**kwargs)
'''执行函数之后要做的'''
return re
return inner
装饰器-进阶版
嵌套装饰器
import time
def wrapper(*args):
def inner(f):
print('inner', args)
def inner2(*args,**kwargs):
print('inner2',args)
ret = f(*args,**kwargs) # ret = func(args,kwargs)
return ret
return inner2
return inner
@wrapper(input('<<')) # func = wrapper(input)(func) func = inner2
def func(a,b):
time.sleep(0.1)
print(a,b)
return 111
func(5,6) # inner2(5,6)
多个装饰器装饰一个函数
def wrapper1(func):
def inner(a):
print('wrapper1 ,before func',a)
func(1)
# print(id(func))
print('wrapper1 ,after func',a)
return inner
def wrapper2(func):
def inner(a):
print('wrapper2 ,before func',a)
func(2)
# print(id(func))
print('wrapper2 ,after func',a)
return inner
@wrapper2 # f = wrapper2(f f = inner
@wrapper1 # f = wrapper1(f f = inner
def f(a):
print('in f',a)
f(1)
开闭原则
1.对扩展是开放的
为什么要对扩展开放呢?
我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
2.对修改是封闭的
为什么要对修改封闭呢?
就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
装饰器完美的遵循了这个开放封闭原则。