什么是装饰器?
装饰器就是用来装饰函数。
- 想要增强原有函数的功能
- 但不希望修改原有函数的定义
- 在代码运行期间动态增加功能的方式
函数嵌套函数
调用方式:
原函数 = 外层函数(原函数名)
原函数
def desc(fun):
def add_info():
print('happy today')
fun()
print('westos_linux')
return add_info
def login():
print('login..')
login = desc(login)
login()
def add_info(fun):
print('happy today')
fun()
print('westos_linux')
def login():
print('login..')
def logout():
print('logout..')
def save():
print('save..')
def trans():
print('trans')
add_info(login)
add_info(logout)
login = add_info(login)
装饰器使用
定义的装饰器实质是返回函数的高阶函数
@timeIt(装饰器名) 这里是 python 提供的一个语法糖
1.解决问题:函数执行前后添加功能-->会改变函数调用命令
2.不改变原有函数的调用方式-->函数里面嵌套函数,并且不改变返回嵌套函数的调用方式-->login = desc(login)
计时装饰器
需求:获取每个函数的执行时间
#1.函数执行之前计算时间
#2.函数执行之后计算时间
import random
import string
import time
from functools import reduce
li = [random.choice(string.ascii_letters +string.digits) for i in range(10) ]
def timeit(fun):
def wrapper(*args,**kwargs):
t1=time.time()
res = fun(*args,**kwargs)
t2 = time.time()
grot = t2-t1
print("所需时间:%.6f" %grot)
return res
return wrapper
@timeit
def myjoin(*args,**kwargs):
s = ','.join(*args,**kwargs)
print(s)
myjoin(li)
日志装饰器
#创建装饰器
#1.创建add_log装饰器,被装饰函数打印日志信息
#2.日志格式为:[字符串时间] 函数名:XXX 运行时间:XXXX 运行返回值结果:XXXX
import time
import functools
import math
def add_log(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
run_time =time.ctime()
start_time = time.time()
res = fun(*args,**kwargs)
end_time = time.time()
na = fun.__name__
print('[字符串时间:%s] 函数名:%s 运行时间:%.6f 运行返回值结果:%s' %(run_time,na,end_time-start_time,res))
return res
return wrapper
@add_log
def mymult(x,y):
"""这是一个求x的y次方的函数"""
return math.pow(x,y)
mymult(2,3)
登陆验证
#用户登录验证的装饰器is_login
# 如果用户登陆成功,则执行被装饰的函数
# 如果用户登陆不成功,则执行登陆函数
users =['root','sheen']
def is_login(fun):
def wrapper(*args,**kwargs):
if kwargs.get('name') in users:
res = fun(*args,**kwargs)
else:
res = login()
return res
return wrapper
@is_login
def writeblog(name):
return "wirte,now.."
def login():
return 'please login..'
print(writeblog(name='star'))
类型判断(无参)
#1.基础版(无参数)
#编写装饰器required_ints
# 确保函数收到的每一个参数都是整数
# 如果参数不是整形数,打印TypeError
import functools
def required_ints(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
for i in args:
if not isinstance(i,int):
print('TypeError')
break
else:
res = fun(*args,**kwargs)
return res
return wrapper
@required_ints
def myadd(a,b):
return a+b
print(myadd(1,2.0))
含参类型判断
# #带参数的装饰器
# """
# 装饰器为required_types
# 当装饰器为@required_types(int,float),确保函数接收到的每一个参数都是int/float类型
# 当装饰器为@required_types(list),确保函数接收到的每一个参数都是list类型
# 当装饰器为@required_types(str,int),确保函数接收到的每一个参数都是str/int类型
# 如果参数不满足条件,打印TypeError,参数必须是XXXXX类型
import functools
def required_types(*kinds): #kinds元组
def required_ints(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
for i in args:
if not isinstance(i,kinds):
print('TypeError,参数类型为',kinds)
break
else:
res = fun(*args,**kwargs)
return res
return wrapper
return required_ints
@required_types(int,str)
def my(a,b):
return a,b
print(my(1,'sdhs'))
带有多个装饰器
def makebold(fun):
print("makebold")
def wrapper1(*args,**kwargs):
print("bold")
return fun(*args,**kwargs)
return wrapper1
def makei(fun):
print("makei")
def wrapper(*args,**kwargs):
print("i")
return fun(*args, **kwargs)
return wrapper #wrapper=login
#当有多个装饰器时,从下到上调用装饰器
#真实wrapper内容是从上到下执行的
@makebold #login = makebold(login) #login为wrapper1
@makei #login = makei(login) #login为wrapper
def login():
return "登陆"
print(login())
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。