一、什么是装饰器
- 用来给其他固定函数增加其他功能的一种函数。
- 装饰器的实现是函数里面嵌套函数,让其他函数在不需要做任何代码改动的前提下增加额外功能。
- 装饰器需要传递一个函数,返回值也是一个函数对象
二、装饰器的应用举例
1.需求:用户登陆验证的装饰器,如果用户登陆成功,则执行被装饰的函数,如果登陆失败,则执行登陆函数
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 def login(): return '登陆。。。' @is_login #将装饰器加到需要被装饰的函数上面 def writeBlog(name): return '编写博客。。' print writeBlog(name='adminss')
2.map函数和匿名函数lambda
map函数:第一个参数为一个函数,第二个参数是一个序列(就相当于为第一个参数的参数)
def f(x): return x*x # map()传入的第一个参数是一个函数,第二个参数是一个序列 print map(f,[1,2,3,4]) print map(lambda x:x*x,[1,2,3,4]) #当不知道函数要起什么名字的时候就叫lambda
3.多个装饰器的用法以及调用顺序
调用规则:依次从下往上调用
需求:先验证是否登陆成功再验证权限
def is_root(fun): #此装饰器用来验证是否有root权限 @functools.wraps(fun) #此语句用来显示被装饰函数的名字及内部的注释块信息 def wrapper(*args, **kwargs): # inspect.getcallargs返回值是字典,key值为:形参 value值:形参对应的实参 inspect_res = inspect.getcallargs(fun, *args, **kwargs) print 'inspect_res的返回值:%s' % inspect_res if inspect_res.get('name') == 'root': res = fun(*args, **kwargs) return res else: print 'Error:no permisson add studnet' return wrapper login_session = ['root', 'admin', 'redhat'] #用户名列表 def is_login(fun): #是否登陆成功装饰器 @functools.wraps(fun) def warrper(*args, **kwargs): if args[0] in login_session: res = fun(*args, **kwargs) return res else: print 'Error:%s未登陆!' % args[0] return warrper @is_login @is_root #装饰器起作用是从下往上调用装饰器 def add_student(name): print '添加学生信息。。' add_student('root')
4.带有参数的装饰器
def log(kind): #定义带有一个参数的装饰器 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('westos') #在装饰函数的时候传递参数 def add(x,y): time.sleep(1) return x+y print add(1,2)
5.如何随机生成100个大小写字母
import random import string li = [random.choice(string.ascii_letters) for i in range(100)] #随机生成100个大小写字母
6.需求:编写装饰器required_inits,条件如下:确保函数接收到的每一个参数都是整数,如果参数不是整形数,打印TypeErrot:参数必须为整形
import functools def required_ints(fun): @functools.wraps(fun) def wrapper(*args, **kwargs): for i in args: #遍历函数fun传进来的参数 if not isinstance(i, int): 判断是否为整数 print 'TypeError:参数必须为整形' 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 add(1,2) print myMax(1,2,3,4)