装饰器(十五)
import time def timer(func): def swapper(*args,**kargs): start_time = time.time() res = func(*args,**kargs) end_time = time.time() print(end_time-start_time) return swappe
装饰器:本质就是函数,用来给其他函数增加 附加功能
原则:
1.不修改被修饰函数的源代码
2.不修改被修饰函数的调用方式
装饰器 = 高阶函数 + 函数嵌套 +闭包
高阶函数:
1.函数的参数是一个函数名
2.函数的返回值是一个函数名
3.满足以上两个条件中的一个就是高阶函数
import time def foo(): time.sleep(2) def test_swapper(func): time_start = time.time() func() time_end = time.time() print('函数执行时间:%s' %(time_end - time_start)) test_swapper(foo) # 修改了函数的调用方式 foo() ''' 函数执行时间:2.0000498294830322 '''
import time def foo(): time.sleep(2) print('from foo...') def test_swapper(func): time_start = time.time() func() time_end = time.time() print('函数执行时间:%s' %(time_end - time_start)) return func foo = test_swapper(foo) foo() ''' from foo... 函数执行时间:2.0009238719940186 from foo... # 多执行了一次 '''
以上说明高阶函数一个人满足不了装饰器的条件
函数嵌套和函数闭包
内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包
闭包似有化了变量,原来需要类对象完成的工作,闭包也可以完成
闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存
# 嵌套和闭包 def father(name): def son(): print('father is %s' % name) def grandson(): print('grandfather is %s' %name) grandson() son() print(locals()) father('world') ''' father is world grandfather is world {'son': <function father.<locals>.son at 0x000002287CA55C80>, 'name': 'world'} '''
高阶函数 + 函数嵌套 +闭包
# 框架 def timer(func): def wapper(): pass return wapper()
import time def foo(): time.sleep(2) print('from foo...') def test_swapper(func): def son(): time_start = time.time() func() time_end = time.time() print('函数执行时间:%s' %(time_end - time_start)) return son foo = test_swapper(foo)
#@timer 就相当于 foo = timer(foo)
foo() ''' from foo... 函数执行时间:2.0008609294891357 '''
#@timer 就相当于 foo = timer(foo),故可以如下写,就是装饰器的简单实现
import time # # 框架 # def timer(func): # def wapper(): # pass # return wapper() def timer(func): def swapper(): time_start = time.time() func() time_end = time.time() print('函数执行时间:%s' %(time_end - time_start)) return swapper @timer def foo(): time.sleep(2) print('from foo...') #foo = timer(foo) # @timer 就相当于 foo = timer(foo) foo()
加返回值
import time # # 框架 # def timer(func): # def wapper(): # pass # return wapper() def timer(func): def swapper(): time_start = time.time() res = func() time_end = time.time() print('函数执行时间:%s' %(time_end - time_start)) return res return swapper @timer def foo(): time.sleep(2) print('from foo...') return 123 #foo = timer(foo) # @timer 就相当于 foo = timer(foo) res = foo() print(res) ''' from foo... 函数执行时间:2.0008599758148193 123 '''
加参数:
import time def timer(func): def swapper(*args,**kargs): start_time = time.time() res = func(*args,**kargs) end_time = time.time() print(end_time-start_time)
return res return swapper @timer def foo(name,age): print('name:%s,age:%s' %(name,age)) time.sleep(1)
return 123 res = foo('mike',18)
简单应用
cur_user = {'name':None, 'certify':False} # 装饰器可以带参数 def certify_choice(choice = 'txt'): print('认证方式是:%s' %(choice)) def certify(func): def wrapper(*args, **kargs): # 如果已经认证就不需要再认证 if cur_user['name'] == None and cur_user['certify'] == False: name = input('用户名:').strip() password = input('登录密码:').strip() with open('./用户信息','r') as read_file: for info in read_file: eval_info = eval(info) # 将取出的字符串转为数据类型 #print(eval_info['name'],eval_info['password']) if name == eval_info['name'] and int(password) == eval_info['password']: cur_user['name'] = name cur_user['certify'] = True break else: print('当前用户名或密码错误') read_file.close() func(*args, **kargs) return wrapper return certify @certify_choice() def index(): print('welcome to the page') @certify_choice() def home(): print('this is home page') @certify_choice() def shopping(): print('the track has : milk, fruit, ...') # 这条语句可以用来调试当前程序的函数 if __name__ == '__main__': index() home() shopping()
用户信息 {'name':'a', 'password':111} {'name':'b', 'password':222} {'name':'c', 'password':333} {'name':'d', 'password':444}