1、用戶登陸驗(yàn)證的裝飾器
需求:用戶登陸驗(yàn)證的裝飾器is_login
1.如果用戶登陸成功,則執(zhí)行被裝飾的函數(shù)
2。如果用戶登陸不成功,則執(zhí)行登陸函數(shù)
import functools login_users=['admin','root'] def is_login(fun): @functools.wraps(fun) #保留原函數(shù)的屬性 def wrapper(*args,**kwargs): #判斷寫博客這個(gè)用戶是否登陸成功 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、獲取每個(gè)函數(shù)的執(zhí)行時(shí)間
裝飾器的需求:獲取每個(gè)函數(shù)的執(zhí)行時(shí)間
1.函數(shù)執(zhí)行之前計(jì)算時(shí)間
2.函數(shù)執(zhí)行之后計(jì)算時(shí)間
問題一:被裝飾的函數(shù)有返回值的時(shí)候怎么辦?
問題二:如何保留被裝飾函數(shù)的函數(shù)名和幫助文檔信息(functools.wraps(fun))
實(shí)驗(yàn)一:看字符串拼接的效率 1)"hello"+"world" 2)用Python的內(nèi)置函數(shù) ‘ ’.join('hello','world')
實(shí)驗(yàn)二:檢測列表生成式和內(nèi)置函數(shù)map的效率高低,n為函數(shù)傳入的參數(shù) 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): """這是一個(gè)裝飾器timeit""" @functools.wraps(fun) #可以保留被裝飾函數(shù)的函數(shù)名和幫助文檔信息 def wrapper(*args,**kwargs): #接收可變參數(shù)和關(guān)鍵字參數(shù) """這是一個(gè)wrapper函數(shù)""" #args:元組kwargs:字典 #函數(shù)執(zhí)行之前的時(shí)間 start_time = time.time() #執(zhí)行函數(shù) #接受被裝飾函數(shù)的返回值 res = fun(*args,**kwargs) #args解包,|對于元組解包,對于字典解包 #函數(shù)執(zhí)行之后 end_time =time.time() print '運(yùn)行時(shí)間為:%.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) #每個(gè)字母之間以‘,’隔開 @timeit def fun_list(n): """這是fun_list函數(shù),被timeit裝飾""" return [2*i for i in range(n)] @timeit def fun_map(n): """這是fun_map函數(shù)""" 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__
問題一原函數(shù)有返回值,加上裝飾器如何拿到返回值的解決方案
def outer(fun): def wrapper(strs): print '哈哈' res =fun(strs) return res #返回原函數(shù)的返回值 print 'hello world!' return wrapper @outer def func1(arg): print 'this is func1',arg return '100' #這是原函數(shù)的返回值 #調(diào)用函數(shù)時(shí),傳入一個(gè)字符串作為參數(shù) aa = func1('my name is tantianran') print aa
3.map和匿名函數(shù)
def f(x): return x*x # map()傳入的第一個(gè)參數(shù)是一個(gè)函數(shù),第二個(gè)參數(shù)是一個(gè)序列 print map(f,[1,2,3,4]) print map(lambda x:x*x,[1,2,3,4])
4.被裝飾函數(shù)打印日志信息
創(chuàng)建裝飾器,需求如下:
1.創(chuàng)建add_log裝飾器,被裝飾的函數(shù)打印日志信息
2.日志格式為:[字符串時(shí)間] 函數(shù)名/:xxx,運(yùn)行時(shí)間:xxx,運(yùn)行返回值結(jié)果: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] 函數(shù)名:%s,運(yùn)行時(shí)間:%.5f,運(yùn)行返回值結(jié)果:%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.編寫裝飾器,確保打印整數(shù)
編寫裝飾器required_ints,條件如下:
1)確保函數(shù)接收到的每個(gè)參數(shù)都是整數(shù);
2)如果參數(shù)不是整形數(shù),打印TypeError:參數(shù)必須為整形
import functools def required_ints(fun): @functools.wraps(fun) def wrapper(*args, **kwargs): for i in args: if not isinstance(i, int): print 'TypeError:參數(shù)必須為整形' 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.編寫裝飾器判斷輸入?yún)?shù)的類型
編寫裝飾器required_types,條件如下:
1)當(dāng)裝飾器為@required_types(int,float) 確保函數(shù)接收到的每個(gè)參數(shù)都是int或是float類型;
2)當(dāng)裝飾器為@required_types(list) 確保函數(shù)接收到的每個(gè)參數(shù)都是list類型
3)當(dāng)裝飾器為@required_types(str,int) 確保函數(shù)接收到的每個(gè)參數(shù)都是str或是int類型
4)如果參數(shù)不滿足條件,打印TypeError:參數(shù)必須為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:參數(shù)必須為',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)