Python 装饰器解析
一、装饰器定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能
二、装饰器的作用:在不改变原函数的情况下,为原函数前后添加新的功能
三、装饰器的原则:
1、不能修改被装饰的函数的源代码
2、不能修改被装饰函数的调用方式
四、装饰器的组成:由作用域、高阶函数以及闭包组成
闭包的概念:如果在一个内部函数里面,对外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包
五、装饰器模板:
需要注意的是带参数的装饰器执行顺序为先执行@符号后面的内容,即先将参数传进装饰器中
def wrapper(func): def inner(*args,**kwargs): '被装饰函数之前添加的内容' ret = func(*args,**kwargs) '被装饰函数之后添加的内容' return ret return inner
def outer(形参) def wrapper(func): def inner(*args,**kwargs): '被装饰函数之前添加的内容' ret = func(*args,**kwargs) '被装饰函数之后添加的内容' return ret return inner return wrapper @outer(True) def 原函数()
六、装饰器实例
实例一、
# 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),
# 2.要求登录成功一次,后续的函数都无需再输入用户名和密码
"""
思路:
1、首先写两个其他需要被装饰的函数
2、然后写装饰器函数模板
3、补充优化装饰器函数的内容,即登录功能的验证
"""
代码:
FLAG = False #设置状态,用来判断当前是否已经成功登陆 def login(func): def inner(*args, **kwargs): global FLAG if FLAG: ret = func(*args, **kwargs) return ret else: username = input('请输入用户名:') password = input('请输入密码:') if username == 'bangsheng' and password == '123456': FLAG = True #成功登陆后改变状态值 ret = func(*args, **kwargs) # func是被装饰的函数 return ret else: print('登录失败') return inner @login def shop_add(): print('添加一件商品') #多个装饰器装饰一个函数,执行顺序为先执行离def最近的那个装饰器,这里表示先执行@log这个装饰器 @login def shop_del(): print('删除一件商品')
shop_add()
shop_del()
实例二、
# 2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
import time def log(func): def inners(*args, **kwargs): with open('log', 'a', encoding='utf-8') as f: f.write(str(time.strftime('%Y-%m-%d %H:%M:%S')) + ' ' + (func.__name__ + '\n')) ''' time.strftime为格式化输出时间, time.time()获取的时间格式为1970年到现在的秒数 time.local.time()获取到的也是秒数 ''' ret = func(*args, **kwargs) return ret return inners @log def shop_add(): print('添加一件商品') @log def shop_del(): print('删除一件商品') shop_add() shop_del()
实例三、多个装饰器装饰同一个函数
#多个装饰器装饰一个函数,执行顺序为先执行离def最近的那个装饰器,这里表示先执行@log这个装饰器
1 import time 2 3 FLAG = False 4 5 6 def login(func): 7 def inner(*args, **kwargs): 8 global FLAG 9 if FLAG: 10 ret = func(*args, **kwargs) 11 return ret 12 else: 13 username = input('请输入用户名:') 14 password = input('请输入密码:') 15 if username == 'bangsheng' and password == '123456': 16 FLAG = True 17 ret = func(*args, **kwargs) # func是被装饰的函数 18 return ret 19 else: 20 print('登录失败') 21 22 return inner 23 24 25 # 2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件 26 def log(func): 27 def inners(*args, **kwargs): 28 with open('log', 'a', encoding='utf-8') as f: 29 f.write(str(time.strftime('%Y-%m-%d %H:%M:%S')) + ' ' + (func.__name__ + '\n')) 30 ''' 31 time.strftime为格式化输出时间, 32 time.time()获取的时间格式为1970年到现在的秒数 33 time.local.time()获取到的也是秒数 34 ''' 35 ret = func(*args, **kwargs) 36 return ret 37 38 return inners 39 40 41 @login 42 @log 43 def shop_add(): 44 print('添加一件商品') 45 46 #多个装饰器装饰一个函数,执行顺序为先执行离def最近的那个装饰器,这里表示先执行@log这个装饰器 47 @login 48 @log 49 def shop_del(): 50 print('删除一件商品') 51 52 53 shop_add() 54 shop_del()
实例四、带参数的装饰器
'''
通过一个带参数的装饰器可以整体控制装饰器是否生效
只需要在全局变量中将FLAGE的状态变化为False就可以使装饰器失效
'''
1 ''' 2 带参数的装饰器,可以通过一个参数来控制装饰器是否被启用 3 ''' 4 5 FLAGE = True 6 def timmer_outer(FLAGE): 7 def timmer(func): 8 def inner(*args,**kwargs): 9 if FLAGE: 10 start = time.time() 11 ret = func(*args,**kwargs) 12 end = time.time() 13 print(start-end) 14 return ret 15 else: 16 ret = func(*args,**kwargs) 17 return ret 18 return inner 19 return timmer 20 21 ''' 22 通过一个带参数的装饰器可以整体控制装饰器是否生效 23 只需要在全局变量中将FLAGE的状态变化为False就可以使装饰器失效 24 ''' 25 @timmer_outer(FLAGE) 26 def nufront(): 27 time.sleep(0.1) 28 print('新岸线公司') 29 30 @timmer_outer(FLAGE) 31 def hst(): 32 time.sleep(0.2) 33 print('HST')