装饰器
案例1:
创建装饰器,要求如下:
1. 创建add_log装饰器,被装饰的函数打印日志信息;
2. 日志格式为: [字符串时间] 函数名: xxx, 运行时间:xxx, 运行返回值结果:xxx
代码:
import time
import functools
# 定义装饰器
def add_log(fun):
# 保留被装饰函数的函数名和帮助信息文档
@functools.wraps(fun)
def inter(*args,**kwargs):
# time.time(): 秒数
start_time = time.time()
# 由于被装饰函数有返回值
res = fun(*args,**kwargs)
end_time = time.time()
# 运行返回值结果:即为函数的返回值,fun.__name__:返回函数名
print('[%s] 函数名:%s, 运行时间:%.6f, 运行返回值结果:%d'
%(time.ctime(),fun.__name__,end_time - start_time,res))
# 所以必须return返回函数返回值
return res
return inter
# 添加装饰
@add_log
# 定义被装饰函数(求任意两个数的和)
def add(x,y):
# 休眠1秒
time.sleep(1)
return x+y
# 调用函数
print(add(1,10))
# 输出时间; time.ctime():以正常的格式显示时间
# print(time.ctime())
需求:
仅root用户可以有权限执行以下函数,当普通用户执行时会报错
#提示: 如何返回函数的实参?
inspect.getcallargs(函数名,参数):以字典的形式返回函数的参数 ( {形参:实参} )
get方法:返回字典指定key的value值
代码:
import functools
import inspect
# 定义装饰器
def is_root(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
# inspect.getcallargs:以字典的形式返回函数的参数
# key值为:形参,value值为:形参对应的实参
inspect_res = inspect.getcallargs(fun,*args,**kwargs)
print('inspect_res的返回值为:%s' % inspect_res)
# get方法:返回字典指定key的value值
if inspect_res.get('name') == 'root':
res = fun(*args,**kwargs)
return res
else:
print('ERROR:you are not a root user')
return wrapper
# 添加装饰
@is_root
# 定义被装饰的函数
def add_student(name):
print('添加学生信息...')
# 调用函数
add_student('westos')
先让用户登陆,再判断用户是否由权限执行添加信息功能
代码:
import functools
import inspect
userlist = ['root','admin','student']
# 定义装饰器1(判断用户是否登陆成功)
def user_login(fun):
@functools.wraps(fun)
def logins(*args,**kwargs):
for i in args:
if i not in userlist:
print('Error:登陆失败')
else:
print('登陆成功')
res = fun(*args,**kwargs)
return res
return logins
# 定义装饰器2(判断用户是否为root用户)
def is_root(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
# inspect.getcallargs:以字典的形式返回函数的参数
# key值为:形参,value值为:形参对应的实参
inspect_res = inspect.getcallargs(fun,*args,**kwargs)
print('inspect_res的返回值为:%s' % inspect_res)
# get方法:返回字典指定key的value值
if inspect_res.get('name') == 'root':
res = fun(*args,**kwargs)
return res
else:
print('ERROR:you are not a root user')
return wrapper
# 添加装饰(装饰器的内部功能函数从上到下依次执行)
@user_login
@is_root
# 定义被装饰的函数
def add_student(name):
print('添加学生信息...')
# 调用函数
add_student('admin')
编写装饰器required_ints, 条件如下:
1). 确保函数接收到的每一个参数都是整数;
# 提示:如何判断变量的类型?
type(s) # 输出s的类型
isinstance(s,str) # 判断s是否为字符串类型
2). 如果参数不是整形数,抛出异常: 参数必须为整形;
# 提示:如何抛出异常?
raise TypeError(“参数必须为整形”)
代码:
import functools
# 定义装饰器
def required_ints(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
# 遍历整个想要求和的元组
for i in args + tuple(kwargs.values()):
# 判断每个元素是否为整型,如果不是,则抛出异常
if not isinstance(i,int):
# raise TypeError(): 抛出异常
raise TypeError('参数必须为整形')
else:
# 调用函数,并返回函数返回值
res = fun(*args,**kwargs)
return res
return wrapper
# 添加装饰
@required_ints
# 定义被装饰函数:
# *args:可变参数 **kwargs:关键字参数
def add(*args,**kwargs):
# args:字典类型 kwargs.values():元组类型
# 由于数据类型不同,所以不能直接用+来连接,必须先转换数据类型
return sum(args + tuple(kwargs.values()))
# 注意:如果有字典类型的实参,则必须写在最后边
print(add(1,2.0,a=3,b=5))