1、用户登陆验证的装饰器
需求:用户登陆验证的装饰器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 def login(): return '登陆...' @is_login def writerBlog(name): return '编写博客...' print writerBlog(name='admin')
2、获取每个函数的执行时间
装饰器的需求:获取每个函数的执行时间
1.函数执行之前计算时间
2.函数执行之后计算时间
问题一:被装饰的函数有返回值的时候怎么办?
问题二:如何保留被装饰函数的函数名和帮助文档信息(functools.wraps(fun))
实验一:看字符串拼接的效率 1)"hello"+"world" 2)用Python的内置函数 ‘ ’.join('hello','world')
实验二:检测列表生成式和内置函数map的效率高低,n为函数传入的参数 1)[2*i for i in range(n)] 2)list(map(lambda x:x*2,range(n)))
import random import string import functools #print string.ascii_letters #abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ import time li =[random.choice(string.ascii_letters) for i in range(10)]#输出大小写字母 def timeit(fun): """这是一个装饰器timeit""" @functools.wraps(fun) #可以保留被装饰函数的函数名和帮助文档信息 def wrapper(*args,**kwargs): #接收可变参数和关键字参数 """这是一个wrapper函数""" #args:元组kwargs:字典 #函数执行之前的时间 start_time = time.time() #执行函数 #接受被装饰函数的返回值 res = fun(*args,**kwargs) #args解包,|对于元组解包,对于字典解包 #函数执行之后 end_time =time.time() print '运行时间为:%.6f'%(end_time-start_time) return res return wrapper @timeit def con_add(): s='' for i in li: s+=(i+',') print s @timeit def join_add(): print ','.join(li) #每个字母之间以‘,’隔开 @timeit def fun_list(n): """这是fun_list函数,被timeit装饰""" return [2*i for i in range(n)] @timeit def fun_map(n): """这是fun_map函数""" return list(map(lambda x:x*2,range(n))) con_add() join_add() print fun_map(10000) print fun_list(10000) #wrapper(10) print fun_list.__name__ print fun_list.__doc__
问题一原函数有返回值,加上装饰器如何拿到返回值的解决方案
def outer(fun): def wrapper(strs): print '哈哈' res =fun(strs) return res #返回原函数的返回值 print 'hello world!' return wrapper @outer def func1(arg): print 'this is func1',arg return '100' #这是原函数的返回值 #调用函数时,传入一个字符串作为参数 aa = func1('my name is tantianran') print aa
3.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])
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.编写装饰器,确保打印整数
编写装饰器required_ints,条件如下:
1)确保函数接收到的每个参数都是整数;
2)如果参数不是整形数,打印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 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.0)
6.编写装饰器判断输入参数的类型
编写装饰器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(*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(float,float) def add(a, b): return a + b print add(1.1,3)