一、装饰器定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能
二、装饰器的作用:在不改变原函数的情况下,为原函数前后添加新的功能
三、装饰器的原则:
1、不能修改被装饰的函数的源代码
2、不能修改被装饰函数的调用方式
四、装饰器的组成:由作用域、高阶函数以及闭包组成
闭包的概念:如果在一个内部函数里面,对外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包
五、装饰器模板:
需要注意的是带参数的装饰器执行顺序为先执行@符号后面的内容,即先将参数传进装饰器中
defwrapper(func):def inner(*args,**kwargs):'被装饰函数之前添加的内容'ret= func(*args,**kwargs)'被装饰函数之后添加的内容'
returnretreturn inner
普通装饰器模板
defouter(形参)defwrapper(func):def inner(*args,**kwargs):'被装饰函数之前添加的内容'ret= func(*args,**kwargs)'被装饰函数之后添加的内容'
returnretreturninnerreturnwrapper
@outer(True)def 原函数()
带参数的装饰器模板
六、装饰器实例
实例一、
# 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),
# 2.要求登录成功一次,后续的函数都无需再输入用户名和密码
"""
思路:
1、首先写两个其他需要被装饰的函数
2、然后写装饰器函数模板
3、补充优化装饰器函数的内容,即登录功能的验证
"""
代码:
FLAG = False #设置状态,用来判断当前是否已经成功登陆
deflogin(func):def inner(*args, **kwargs):globalFLAGifFLAG:
ret= func(*args, **kwargs)returnretelse:
username= input('请输入用户名:')
password= input('请输入密码:')if username == 'bangsheng' and password == '123456':
FLAG= True #成功登陆后改变状态值
ret = func(*args, **kwargs) #func是被装饰的函数
returnretelse:print('登录失败')returninner
@logindefshop_add():print('添加一件商品')#多个装饰器装饰一个函数,执行顺序为先执行离def最近的那个装饰器,这里表示先执行@log这个装饰器
@logindefshop_del():print('删除一件商品')
shop_add()
shop_del()
实例二、
# 2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
importtimedeflog(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)returnretreturninners
@logdefshop_add():print('添加一件商品')
@logdefshop_del():print('删除一件商品')
shop_add()
shop_del()
实例三、多个装饰器装饰同一个函数
#多个装饰器装饰一个函数,执行顺序为先执行离def最近的那个装饰器,这里表示先执行@log这个装饰器
1 importtime2
3 FLAG =False4
5
6 deflogin(func):7 def inner(*args, **kwargs):8 globalFLAG9 ifFLAG:10 ret = func(*args, **kwargs)11 returnret12 else:13 username = input('请输入用户名:')14 password = input('请输入密码:')15 if username == 'bangsheng' and password == '123456':16 FLAG =True17 ret = func(*args, **kwargs) #func是被装饰的函数
18 returnret19 else:20 print('登录失败')21
22 returninner23
24
25 #2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
26 deflog(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 returnret37
38 returninners39
40
41 @login42 @log43 defshop_add():44 print('添加一件商品')45
46 #多个装饰器装饰一个函数,执行顺序为先执行离def最近的那个装饰器,这里表示先执行@log这个装饰器
47 @login48 @log49 defshop_del():50 print('删除一件商品')51
52
53 shop_add()54 shop_del()
多个装饰器装饰同一个函数
实例四、带参数的装饰器
'''
通过一个带参数的装饰器可以整体控制装饰器是否生效
只需要在全局变量中将FLAGE的状态变化为False就可以使装饰器失效
'''
1 '''
2 带参数的装饰器,可以通过一个参数来控制装饰器是否被启用3 '''
4
5 FLAGE =True6 deftimmer_outer(FLAGE):7 deftimmer(func):8 def inner(*args,**kwargs):9 ifFLAGE:10 start =time.time()11 ret = func(*args,**kwargs)12 end =time.time()13 print(start-end)14 returnret15 else:16 ret = func(*args,**kwargs)17 returnret18 returninner19 returntimmer20
21 '''
22 通过一个带参数的装饰器可以整体控制装饰器是否生效23 只需要在全局变量中将FLAGE的状态变化为False就可以使装饰器失效24 '''
25 @timmer_outer(FLAGE)26 defnufront():27 time.sleep(0.1)28 print('新岸线公司')29
30 @timmer_outer(FLAGE)31 defhst():32 time.sleep(0.2)33 print('HST')
带参数的装饰器