装饰器进阶
is_admin装饰器:判断传入的参数是否root;
import functools
import inspect
def is_admin(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
inspect_res = inspect.getcallargs(fun, *args, **kwargs)
print("inspect的返回值: %s" %(inspect_res))
if inspect_res.get('name') == 'root':
temp = fun(*args, **kwargs)
return temp
else:
print("not root/admin user, no permisson add student")
return wrapper
@is_admin # add_student = is_admin(add_student)
def add_student(name):
print("添加学生信息.....")
add_student('redhat')
add_student('root')
inspect的返回值: {'name': 'redhat'}
not root/admin user, no permisson add student
inspect的返回值: {'name': 'root'}
添加学生信息.....
探究多个装饰器的执行顺序
def decorator_a(func):
print('Get in decorator_a')
def inner_a(*args, **kwargs):
print('Get in inner_a')
return func(*args, **kwargs)
return inner_a
def decorator_b(func):
print('Get in decorator_b')
def inner_b(*args, **kwargs):
print('Get in inner_b')
return func(*args, **kwargs)
return inner_b
@decorator_b # f = decorator_b(inner_a) # f = inner_b
@decorator_a # f = decorator_a(f) # f = inner_a
def f(x):
print('Get in f')
return x * 2
f(1)
Get in decorator_a
Get in decorator_b
Get in inner_b
Get in inner_a
Get in f
多个装饰器的应用
import functools
import inspect
login_seesion = ['root', 'admin', 'redhat']
def is_admin(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
inspect_res = inspect.getcallargs(fun, *args, **kwargs)
print("inspect的返回值: %s" %(inspect_res))
if inspect_res.get('name') == 'root':
temp = fun(*args, **kwargs)
return temp
else:
print("Error:not root/admin user, no permisson add student")
return wrapper
def is_login(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
if args[0] in login_seesion:
temp = fun(*args, **kwargs)
return temp
else:
print("Error: %s未登陆!" %(args[0]))
return wrapper
@is_login
@is_admin # is_admin()
def add_student(name):
print("添加学生信息.....")
add_student('aa')
add_student('redhat')
add_student('root')
Error: aa未登陆!
inspect的返回值: {'name': 'redhat'}
Error:not root/admin user, no permisson add student
inspect的返回值: {'name': 'root'}
添加学生信息.....
带参数的装饰器
import time
import functools
import random
def addLog(type):
def add_log(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
start_time = time.time()
res = f(*args, **kwargs)
end_time = time.time()
print("日志信息:[%s] [%s] %s 运行时间为%.5f s 运行结果为%s" %(type.title(),time.ctime(),f.__name__,end_time-start_time,res))
return res
return wrapper
return add_log
@addLog("warn") # hello = addLog(warn')
def hello():
time.sleep(random.random())
return "hello"
@addLog(type="debug")
def add(x,y):
time.sleep(random.random())
return x+y
print(hello())
print(add(1,2))
日志信息:[Warn] [Wed Aug 29 19:28:05 2018] hello 运行时间为0.79795 s 运行结果为hello
hello
日志信息:[Debug] [Wed Aug 29 19:28:06 2018] add 运行时间为0.76612 s 运行结果为3
3
带有参数装饰器的练习–参数检测
编写装饰器required_ints, 条件如下:
1). 确保函数接收到的每一个参数都是整数;
2). 如果参数不是整形数, 打印 TypeError:参数必须为整形
编写装饰器required_types, 条件如下:
1). 当装饰器为@required_types(int,float)确保函数接收到的每一个参数都是int或者float类型;
2). 当装饰器为@required_types(list)确保函数接收到的每一个参数都是list类型;
3). 当装饰器为@required_types(str,int)确保函数接收到的每一个参数都是str或者int类型;
4). 如果参数不满足条件, 打印 TypeError:参数必须为xxxx类型
def required_types(*types):
def required(f):
def wrapper(*args, **kwargs):
for i in args:
if not isinstance(i, types):
print("Error:参数必须为",types)
break
else:
res = f(*args, **kwargs)
return res
return wrapper
return required
@required_types(int,float)
def add(x, y):
return x + y
print(add(1, 2e+9))
装饰器总结
def 装饰器名称(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
res = fun(*args, **kwargs)
return res
return wrapper
def 装饰器名称(*args, **kwargs):
def inner(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
res = fun(*args, **kwargs)
return res
return wrapper
return inner
@functools.wraps(f)
inspect.getcallargs(f,*args,**kwargs)