Python装饰器
Posted zhangzixiang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python装饰器相关的知识,希望对你有一定的参考价值。
一.相关定义
补:__iter__() == iter()
装饰器:本质就是函数,为其它函数添加附加功能
原则:
1. 不修改被修饰函数的源代码
2. 不修改被修饰函数的接口(即调用方式)
装饰器的知识储备
装饰器 = 高阶函数 + 函数嵌套 + 函数闭包
def cal(l): start_time = time.time() res = 0 for i in l: time.sleep(0.1) res+=i stop_time = time.time() print(‘函数的运行时间是%s‘ %(stop_time-start_time)) return res print(cal(range(10))) result: 函数的运行时间是1.0016779899597168 45
import time def timmer(func): def wrapper(*args,**kwargs): start_time = time.time() res = func(*args,**kwargs) stop_time = time.time() print(‘函数运行的时间是%s‘ %(stop_time-start_time)) return res return wrapper @timmer def cal(l): res = 0 for i in l: time.sleep(0.1) res+=i return res print(cal(range(10))) result: 函数运行的时间是1.0017824172973633 45
二.高阶函数
1. 函数接收的参数是函数名
2. 函数返回值是一个函数名
3. 满足上述任意一条的都是高阶函数
接收的值是函数名
import time def foo(): time.sleep(3) print(‘hello‘) def test(func): #print(func) start_time = time.time() func() stop_time = time.time() print(‘函数运行时间是 %s‘ %(stop_time - start_time)) test(foo) #违反了装饰器的原则,调用方式改变了 resut: hello 函数运行时间是 3.0026164054870605
调用方式不改变
def foo(): print(‘from the foo‘) def test(func): return func # res = test(foo) # # res() foo = test(foo) foo() result: from the foo
不修改源代码,不修改调用方式
import time def foo(): time.sleep(3) print(‘from the foo‘) def timer(func): #print(func) start_time = time.time() func() stop_time = time.time() print(‘函数运行时间是 %s‘ %(stop_time - start_time)) return func foo = timer(foo) foo() result: from the foo 函数运行时间是 3.001885414123535 from the foo
多运行了一次! 高阶函数实现不了装饰器的功能
三.函数嵌套
#函数嵌套 def father(name): print(‘from father %s‘ %name) def son(): print(‘from the son‘) print(locals()) father(‘Joey‘) result: from father Joey {‘son‘: <function father.<locals>.son at 0x7f4acb23d620>, ‘name‘: ‘Joey‘}
函数嵌套 -->> 函数闭包
四.函数闭包
#装饰器的框架 import time def timer(func): def wrapper(): start_time = time.time() func() #就是下运行test stop_time = time.time() print(‘运行时间是%s‘ %(stop_time-start_time)) return wrapper def test(): time.sleep(1) print(‘test函数运行完毕‘) test = timer(test) #返回wrapper的地址 test() #执行wrapper函数 result: test函数运行完毕 运行时间是1.0012073516845703
@timer == test=timer(test)
#装饰器的框架 import time def timer(func): def wrapper(): start_time = time.time() func() #就是下运行test stop_time = time.time() print(‘运行时间是%s‘ %(stop_time-start_time)) return wrapper @timer #写在timer()后面 def test(): time.sleep(1) print(‘test函数运行完毕‘) #test = timer(test) #返回wrapper的地址 test() #执行wrapper函数
进一步改进,加上返回值
#装饰器的框架 import time def timer(func): def wrapper(): start_time = time.time() res = func() #就是下运行test stop_time = time.time() print(‘运行时间是%s‘ %(stop_time-start_time)) return res return wrapper @timer def test(): time.sleep(1) print(‘test函数运行完毕‘) return ‘这是test的返回值‘ res = test() #返回wrapper的地址 print(res) result: test函数运行完毕 运行时间是1.0005300045013428 这是test的返回值
函数闭包加上参数
#装饰器的框架 import time def timer(func): def wrapper(name,age,gender): start_time = time.time() res = func(name,age,gender) #就是下运行test stop_time = time.time() print(‘运行时间是%s‘ %(stop_time-start_time)) return res return wrapper @timer def test(name,age,gender): time.sleep(1) print(‘test函数运行完毕 姓名:%s ;性别:%s ; 年龄:%d‘ %(name,gender,age)) return ‘这是test的返回值‘ res = test(‘alex‘,18,‘male‘) #返回wrapper的地址 print(res) result: test函数运行完毕 姓名:alex ;性别:male ; 年龄:18 运行时间是1.001114845275879 这是test的返回值
进一步优化,使之能够接收任意长度的参数
#装饰器的框架 import time def timer(func): def wrapper(*args,**kwargs): start_time = time.time() res = func(*args,**kwargs) #就是下运行test stop_time = time.time() print(‘运行时间是%s‘ %(stop_time-start_time)) return res return wrapper @timer def test(name,age,gender): time.sleep(1) print(‘test函数运行完毕 姓名:%s ;性别:%s ; 年龄:%d‘ %(name,gender,age)) return ‘这是test的返回值‘ res = test(‘alex‘,age=18,gender=‘male‘) #返回wrapper的地址 print(res) result: test函数运行完毕 姓名:alex ;性别:male ; 年龄:18 运行时间是1.0011067390441895 这是test的返回值
def test2(name,age,gender): print(name) print(age) print(gender) def test1(*args,**kwargs): test2(*args,**kwargs) test2(‘alex‘,18,gender=‘male‘) test1(‘Joey‘,18,‘male‘) #解压序列 a,b,c = (1,2,3) print(a,b,c) result: alex 18 male Joey 18 male 1 2 3
补: 解压序列
l = (1,2,3,4,5,6,7,8,9,0) # a,b,c = ‘hello‘ # print(a,b,c) # 必须一一对应 a,b,c = ‘hel‘ print(a,b,c) a,*_,c = l print(‘a=%d‘ %a) print(‘c=%d‘ %c) a,*b,c = l print(‘b=%s‘ %b) m=1 n=2 m,n=n,m print(‘m=%d,n=%d‘ %(m,n)) result: h e l a=1 c=0 b=[2, 3, 4, 5, 6, 7, 8, 9] m=2,n=1
五.功能实现
认证功能装饰器
def auth_func(func): def wrapper(*args,**kmargs): username=input(‘用户名:‘).strip() passwd=input(‘密码:‘).strip() if username == ‘alex‘ and passwd == ‘123‘: res = func(*args,**kmargs) else: print(‘用户名或密码错误‘) return res return wrapper @auth_func def index(): print(‘欢迎来到京东主页‘) pass @auth_func def home(): print(‘欢迎回家‘) pass @auth_func def cart(): print(‘购物车里有[%s,%s,%s]‘ %(‘零食‘,‘书籍‘,‘衣服‘)) pass @auth_func def order(): pass index() home() cart() order() result: 用户名:alex 密码:123 欢迎来到京东主页
功能改进: 只登录一次(记录登录状态)
user_dic = {‘username‘:None,‘login‘:False} def auth_func(func): def wrapper(*args,**kmargs): if user_dic[‘username‘] and user_dic[‘login‘]: res = func(*args, **kmargs) return res username=input(‘用户名:‘).strip() passwd=input(‘密码:‘).strip() if username == ‘alex‘ and passwd == ‘123‘: user_dic[‘username‘] = ‘alex‘ user_dic[‘login‘] = ‘123‘ res = func(*args,**kmargs) else: print(‘用户名或密码错误‘) return res return wrapper @auth_func def index(): print(‘欢迎来到京东主页‘) pass @auth_func def home(): print(‘欢迎回家‘) pass @auth_func def cart(): print(‘购物车里有[%s,%s,%s]‘ %(‘零食‘,‘书籍‘,‘衣服‘)) pass @auth_func def order(): pass index() home() cart() order() result: 用户名:alex 密码:123 欢迎来到京东主页 欢迎回家 购物车里有[零食,书籍,衣服]
功能改进,添加用户名密码存储列表
user_list = [ {‘name‘:‘alex‘,‘passwd‘:‘123‘}, {‘name‘:‘Joey‘,‘passwd‘:‘234‘}, {‘name‘:‘Tony‘,‘passwd‘:‘345‘}, ] current_dic = {‘username‘:None,‘login‘:False} def auth_func(func): def wrapper(*args,**kmargs): if current_dic[‘username‘] and current_dic[‘login‘]: res = func(*args, **kmargs) return res username=input(‘用户名:‘).strip() passwd=input(‘密码:‘).strip() for user_dic in user_list: if username == user_dic[‘name‘] and passwd == user_dic[‘passwd‘]: current_dic[‘username‘] = username current_dic[‘login‘] = passwd res = func(*args, **kmargs) return res else: print(‘用户名或密码错误‘) return wrapper @auth_func def index(): print(‘欢迎来到京东主页‘) pass @auth_func def home(name): print(‘欢迎回家%s‘ %name) pass @auth_func def cart(): print(‘购物车里有[%s,%s,%s]‘ %(‘零食‘,‘书籍‘,‘衣服‘)) pass @auth_func def order(): pass index() print(current_dic) home(‘alex‘) result: 用户名:alex 密码:123 欢迎来到京东主页 {‘username‘: ‘alex‘, ‘login‘: ‘123‘} 欢迎回家alex
功能改进,含参装饰器(使得可以用多种数据库)
user_list = [ {‘name‘:‘alex‘,‘passwd‘:‘123‘}, {‘name‘:‘Joey‘,‘passwd‘:‘234‘}, {‘name‘:‘Tony‘,‘passwd‘:‘345‘}, ] current_dic = {‘username‘:None,‘login‘:False} def auth(auth_type=‘filedb‘): def auth_func(func): def wrapper(*args,**kmargs): if current_dic[‘username‘] and current_dic[‘login‘]: res = func(*args, **kmargs) return res username=input(‘用户名:‘).strip() passwd=input(‘密码:‘).strip() for user_dic in user_list: if username == user_dic[‘name‘] and passwd == user_dic[‘passwd‘]: current_dic[‘username‘] = username current_dic[‘login‘] = passwd res = func(*args, **kmargs) return res else: print(‘用户名或密码错误‘) return wrapper return auth_func @auth(auth_type=‘filedb‘) def index(): print(‘欢迎来到京东主页‘) pass @auth def home(name): print(‘欢迎回家%s‘ %name) pass @auth def cart(): print(‘购物车里有[%s,%s,%s]‘ %(‘零食‘,‘书籍‘,‘衣服‘)) pass @auth def order(): pass index() print(current_dic) home(‘alex‘)
user_list = [ {‘name‘:‘alex‘,‘passwd‘:‘123‘}, {‘name‘:‘Joey‘,‘passwd‘:‘234‘}, {‘name‘:‘Tony‘,‘passwd‘:‘345‘}, ] current_dic = {‘username‘:None,‘login‘:False} def auth(auth_type=‘filedb‘): def auth_func(func): def wrapper(*args,**kmargs): print(‘认证类型是%s‘ %auth_type) if auth_type == ‘filedb‘: if current_dic[‘username‘] and current_dic[‘login‘]: res = func(*args, **kmargs) return res username=input(‘用户名:‘).strip() passwd=input(‘密码:‘).strip() for user_dic in user_list: if username == user_dic[‘name‘] and passwd == user_dic[‘passwd‘]: current_dic[‘username‘] = username current_dic[‘login‘] = passwd res = func(*args, **kmargs) return res else: print(‘用户名或密码错误‘) if auth_type == ‘ldap‘: pass else: print(‘无法识别类型‘) return wrapper return auth_func @auth(auth_type=‘filedb‘) def index(): print(‘欢迎来到京东主页‘) pass @auth(auth_type=‘filedb‘) def home(name): print(‘欢迎回家%s‘ %name) pass @auth(auth_type=‘filedb‘) def cart(): print(‘购物车里有[%s,%s,%s]‘ %(‘零食‘,‘书籍‘,‘衣服‘)) pass @auth(auth_type=‘filedb‘) def order(): pass index() print(current_dic) home(‘alex‘) result: 认证类型是filedb 用户名:alex 密码:123 欢迎来到京东主页 {‘username‘: ‘alex‘, ‘login‘: ‘123‘} 认证类型是filedb 欢迎回家alex
以上是关于Python装饰器的主要内容,如果未能解决你的问题,请参考以下文章