函数装饰器
函数装饰器
不想修改函数的调用方式 但是还想在原来的函数前后添加功能。
import time
def outer(f): #装饰器函数
def inner(*args,**kwargs):
start = time.time() # 要装饰的部分
ret = f(*args,**kwargs) #f(1,2) #被装饰的函数
end = time.time() # 要装饰的部分
print(end - start)
return ret+" 元旦好"
return inner
@outer #语法糖 @装饰器函数名 func=outer(func)
def func(a,b): #被装饰的函数
time.sleep(0.01)
print('老板好同事好大家好',a,b)
return '新年好'
l=func(1,2)
print(l)
老板好同事好大家好 1 2
0.02500128746032715
新年好 元旦好
wrap版装饰器
from functools import wraps def deco(func): @wraps(func) #加在最内层函数正上方 他的作用是用来修复注释,如果不加@wrap则注释内容会被自动删除
def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper
带参数的装饰器
def d(a=None): # 定义一个外层函数,给装饰器传参数--role def foo(func): # foo是我们原来的装饰器函数,func是被装饰的函数 def bar(*args, **kwargs): # args和kwargs是被装饰器函数的参数 # 根据装饰器的参数做一些逻辑判断 if a: print("hello world") else: print("欢迎来到首页。") # 调用被装饰的函数,接收参数args和kwargs func(*args, **kwargs) return bar return foo @d() # 不给装饰器传参数,使用默认的'None'参数 def func1(name): print("Hello {}.".format(name)) @d("哈哈") # 给装饰器传一个'哈哈'参数 def func2(name): print("Hello {}.".format(name)) if __name__ == '__main__': func1("Andy") func2("Andy")
欢迎来到首页。
Hello Andy.
hello world
Hello Andy.
装饰器的开发原则
开放封闭原则
开放 : 对装饰函数的扩展是开放的
封闭 : 对被装饰的函数的修改是封闭的
多个装饰器装饰一个函数
def wrapper1(func): def inner1(): print('wrapper1 ,before func') ret = func() print('wrapper1 ,after func') return ret return inner1 def wrapper2(func): def inner2(): print('wrapper2 ,before func') ret = func() print('wrapper2 ,after func') return ret return inner2 def wrapper3(func): def inner3(): print('wrapper3 ,before func') ret = func() print('wrapper3 ,after func') return ret return inner3 @wrapper3 @wrapper2 @wrapper1 def f(): print('cat') return '哈哈哈' print(f())
结果显示
wrapper3 ,before func
wrapper2 ,before func
wrapper1 ,before func
cat
wrapper1 ,after func
wrapper2 ,after func
wrapper3 ,after func
哈哈哈
#多个装饰器对一个函数进行装饰,结果类似于俄罗斯套娃,语法糖在前先被调用的的在套娃的最外层,依次往里。
# def wahaha():
# '''
# 一个打印娃哈哈的函数
# :return:
# '''
# print('娃哈哈')
#
# print(wahaha.__name__) #查看字符串格式的函数名
# print(wahaha.__doc__) #查看注释