# 装饰器的概念
- 装饰器的实现是函数里面嵌套函数;
- 装饰器的本质是一个函数, 它可以让其他函数在不需要做任何代码改动的前提下增加额外的功能;
- 装饰器需要传递一个函数, 返回值也是一个函数对象.
# 装饰器的应用场景
- 计时器
- 记录日志
- 用户登录验证
- 函数参数验证
如图所示,函数func1输出时运用函数outer进行了装饰
显示结果为
import functools #functools模块用于高阶函数:作用与或者返回其它函数的函数。一般来说,对于该模块,任何可调用对象都可以视为一个函数。
import time #引入时间模块
def log(kind): #kind = 'debug'
def add_log(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
start_time = time.time()
#运行程序开始时间
res = fun(*args,**kwargs)
#运行程序
end_time = time.time()
#程序结束时间
print '<%s> [%s] 函数名:%s,运行时间:%.5f,运行的返回值结果%d' \
%(kind,time.ctime(),fun.__name__,end_time-start_time,res)
return res
return wrapper
return add_log
# log('debug') 返回值:add_log
# add = add_log(add)
@log('debug')
def add(x,y):
time.sleep(1)
#延时一秒执行
return x+y
print add(1,2)
练习1
# 编写装饰器required_types, 条件如下:
# 1). 当装饰器为@required_types(int,float)确保函数接收到的每一个参数都是int或者float类型;
# 2). 当装饰器为@required_types(list)确保函数接收到的每一个参数都是list类型;
# 3). 当装饰器为@required_types(str,int)确保函数接收到的每一个参数都是str或者int类型;
# 4). 如果参数不满足条件, 打印 TypeError:参数必须为xxxx类型
import functools
def required_types(*kides):
def required(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
for i in args:
if isinstance(i, kides):
pass
else:
print '函数所有的次参数并非', kides
break
else:
res = fun(*args, **kwargs)
return res
return wrapper
return required
@required_types(str,str)
def add(a, b):
return a + b
print add('hello','python')
练习2
需求:验证用户登陆的装饰器is_login
1.如果用户登陆成功,则执行被装饰的函数
2.如果用户登陆不成功,则执行登陆函数
"""
import functools
login_users = ['admin', 'root']
def is_login(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
# 判断要写博客的这个用户是否登陆成功
if kwargs.get('name') in login_users:
res = fun(*args, **kwargs)
return res
else:
res = login()
return res
return wrapper
@is_login
def writeBlog(name):
return '编写博客'
def login():
return '登陆。。。'
print writeBlog(name='admin')
练习3
编写装饰器required_ints, 条件如下:
# 1). 确保函数接收到的每一个参数都是整数;
# 2). 如果参数不是整形数, 打印 TypeError:参数必须为整形
import functools
def required_ints(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
for i in args:
if isinstance(i,int):
pass
else:
print '函数的所有参数并非整型'
break
else:
res = fun(*args, **kwargs)
return res
return wrapper
@required_ints
def add(a, b):
return a + b
@required_ints
def myMax(a, b, c, d):
return max(a, b, c, d)
print myMax(1,2,3,4.0)
练习4
# 创建装饰器, 要求如下:
# 1. 创建add_log装饰器, 被装饰的函数打印日志信息;
# 2. 日志格式为: [字符串时间] 函数名: xxx, 运行时间:xxx, 运行返回值结果:xxx
"""
import functools
import time
def add_log(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
start_time = time.time()
res = fun(*args,**kwargs)
end_time = time.time()
print '[%s] 函数名:%s,运行时间:%.5f,运行的返回值结果%d' \
%(time.ctime(),fun.__name__,end_time-start_time,res)
return res
return wrapper
@add_log
def add(x,y):
time.sleep(1)
return x+y
print add(1,2)
练习5
带有多个装饰器的函数
# 需求: 用户登陆验证的装饰器is_login
# # 1). 如果用户登陆成功, 则执行被装饰的函数;
# # 2). 如果用户登陆不成功, 则执行登陆函数
# #需求: 判断登陆用户是否未管理员is_admin(此处管理员只有一个为:admin用户)
# # 1).如果用户为管理员, 则执行被装饰的函数;
# # 2).如果用户不是管理员, 则报错;
"""
import functools
login_users = ['admin', 'root']
def is_admin(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
if kwargs.get('name') == 'admin':
res = fun(*args,**kwargs)
return res
else:
return 'Error:您没有权限访问该网站'
return wrapper
def is_login(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
# 判断要写博客的这个用户是否登陆成功
if kwargs.get('name') in login_users:
res = fun(*args, **kwargs)
return res
else:
res = login()
return res
return wrapper
@is_login
@is_admin
def writeBlog(name):
return '编写博客'
def login():
return '登陆。。。'
print(writeBlog(name='root'))