Python基础知识:5:装饰器
来源:互联网 发布:老虎机的算法原理 编辑:程序博客网 时间:2024/05/29 19:50
装饰器的作用就是为已经存在的对象添加额外的功能。
基于开放封闭原则,在不改变调用者的前提下,在调用之前或之后增加一些功能;
当你有100个或更多的调用程序需要同时增加/修改同一个内容时,使用装饰器会非常有用;
案例1:假设100个程序都要同时额外增加一个功能,如在执行程序前打印字符log;
一种实现方式是:把这个功能复制到100个程序中,但缺点是无法灵活控制outer和f的先后执行顺序,且修改起来很麻烦,需要一个程序一个程序的去修改。
这时,就需要一个装饰器来封装一个功能。
#定义装饰器
def outer():#定义在常规程序外的函数outer,作用是打印log
print('log')
#使用装饰器
def f1():
outer()#使用装饰器
print('F1')
def f2():
outer()
print('F2')
def f100():
outer()
print('F100')
#执行程序
print('f1执行效果:')
f1()
print('f2执行效果:')
f2()
print('f100执行效果:')
f100()
执行结果:
要理解装饰器,必须要先理解函数,具体可参考另外篇博文。
函数两个基本知识:
1)函数的执行从上往下,后一个变量/函数会覆盖前一个变量/参数。
def f1():
print(123)
def f1():
print(456)
f1()
#因为执行顺序为从上到下,因此后一个f1会覆盖前一个f1,执行结果为456
函数的执行顺序案例:
2)函数是可以作为整体进行传递的;如果传递的为函数名,而又没有加(),则函数是作为整体去传递
#先将f1作为整体传递给f2的xxx,再执行f2中的函数体,因为f2的函数体xxx(),因此,继续执行f1()
def f1():
print("函数1执行",123)
def f2(xxx):
print("函数2执行",456)
xxx()#会去执行f1()
f2(f1)#将f1传递给xxx,则xxx=f1
执行结果:
装饰器@+函数名,有两大功能:
1)自动执行outer函数,且将其下面装饰的函数名f1当做参数传递给装饰器中的参数;
2)将outer函数的返回值重新赋值给f1
案例2:解释装饰器的工作原理:在装饰器中无其他的函数
案例2-1:无装饰器案例:执行f1()
1)存储返回值
def f1():
print('F1')
return 123#f1有返回值123
f1() #执行f1函数体,执行结果为F1
执行结果:
2)不存储返回值
def f1():
print('F1')
return 123#f1有返回值123
r=f1() #执行f1函数体,并将f1的返回值赋值给r
print(r)#因f1的函数体有返回值,为123,直接打印123
执行结果:
案例2-2:加入装饰器后:执行f1(),会修改原有的f1函数体,而原有的函数体不再被执行
案例解读:
函数从上到下执行,在执行def f1()时,发现其上面的装饰器,会把装饰器下的f1作为参数传递给装饰器,代替装饰器中的参数func;
f1的函数体,将不会被执行,比如:print('F1')就不会出现
装饰器执行后的返回值111,重新赋值给f1,因此f1目前的值为111
执行f1(),就是执行111(),就会出错
1)因为装饰器的返回值为111,而执行f1即执行111(),这个就会出错了
def outer(func):
return "111"
@outer#装饰器
def f1():
print('F1')
return "123"#f1有返回值123
f1()#因f1已经被重新赋值了111,执行f1()即执行111(),因此再执行是就会出错
执行结果:出错的执行结果
2)可以看下f1此时的值;执行结果为111
def outer(func):
return "111"
@outer#装饰器
def f1():
print('F1')
return "123"#f1有返回值123
print(f1)#因f1已经被重新赋值111
案例3:解释装饰器的工作原理:装饰器中内置函数,暂无参数func
案例3-1:装饰器下的函数会传递给装饰器的参数
案例解读:执行装饰器,把f1赋值给func,定义inner函数;装饰器的返回值为inner函数,赋值给f1,此时再执行f1()时,即为执行inner(),结果为"打印inner函数"
#装饰器中有函数
def outer(func):#func为老的f1
def inner():#定义inner,下面inner的函数体
print("执行inner函数体")
return inner #inner代指inner函数的函数体,并将这个函数体赋值为f1
@outer
def f1():
print('执行f1函数体')
return "123"#f1有返回值123
f1()#f1已被重新赋值为inner,因此当执行f1()时,即执行inner()
执行结果:
案例4:解释装饰器的工作原理:装饰器中内置函数,且有参数func。
因f1会被替换成装饰器的返回值,因此,装饰的参数func指的老的f1,新的f1为inner,内层函数无返回值的情况
1)先打印字符log,再执行程序
def outer(func):#func为原有的f1
def inner(): #定义inner函数
print('inner函数:log')
func()#因func代指原来的f1,因此执行原有的f1函数体
return inner#此为装饰器的返回值,被赋值为f1
@outer
def f1():
print('执行f1函数体')
return "123"#f1有返回值123
f1()#即执行装饰器中的inner函数
执行结果:
2)先打印字符log,再执行程序,再打印after:
def outer(func):#func为原有的f1
def inner(): #定义inner函数
print('inner函数:log')
func()#因func代指原来的f1,因此执行原有的f1函数体
print('after')
return inner#此为装饰器的返回值,被赋值为f1
@outer
def f1():
print('执行f1函数体')
return "123"#f1有返回值123
f1()#即执行装饰器中的inner函数
执行结果:
案例5:装饰器内层函数有返回值
先打印字符log,再执行程序,同时取旧程序的返回值,再打印after:
def outer(func):#func为原有的f1
def inner(): #定义inner函数
print('inner函数:log')
r=func()#因func代指原来的f1,因此执行原有的f1函数体,并将旧f1的返回值传递r,即r="f1的返回值123"
print('after')
return r #inner函数最后返回值为人,函数遇到return,下面就不执行了
return inner#此为装饰器的返回值,被赋值为f1
@outer
def f1():
print('执行f1的函数体')
return "f1的返回值123"#f1有返回值123
r=f1()#即执行装饰器中的inner函数,并取inner函数的返回值,即r
print(r)
执行结果:
此处可以总结下装饰器的执行顺序:
案例6和案例7讲解内部函数有参数的情况:
案例6:装饰器中的参数:当f1有参数时,装饰器中也需要输入参数
def outer(func):#func为原有的f1
def inner(a): #定义inner函数
print('inner函数:log')
r=func(a)#因func代指原来的f1,因此执行原有的f1函数体,并将旧f1的返回值传递r,即r="f1的返回值123"
print('after')
return r #inner函数最后返回值为人,函数遇到return,下面就不执行了
return inner#此为装饰器的返回值,被赋值为f1
@outer
def f1(arg):
print(arg)
return "f1的返回值123"#f1有返回值123
r=f1("f1需要加入参数")#需要传递参数
print(r)
执行结果:
案例7:装饰器中的参数:f1...f100的参数个数不一致时,需要使用动态参数
def outer(func):#func为原有的f1
def inner(*args,**kwargs): #定义inner函数,使用动态参数
print('inner函数:log')
r=func(*args,**kwargs)#因func代指原来的f1,因此执行原有的f1函数体,并将旧f1的返回值传递r,即r="f1的返回值123"
print('after')
return r #inner函数最后返回值为人,函数遇到return,下面就不执行了
return inner#此为装饰器的返回值,被赋值为f1
@outer
def f1(arg):
print(arg)
return "f1的返回值123"#f1有返回值123
@outer
def f2(arg1,arg2):
print(arg1,arg2)
return "f2的返回值456"#f1有返回值123
r1=f1('f1传递1个参数')
print(r1)
print('--------执行传递俩参数案例--------')
r2=f2("f2传递参数1","f2传递参数2")
print(r2)
执行结果:
案例链接:https://pan.baidu.com/s/1dFvrRS9 密码:27cj
- Python基础知识:5:装饰器
- Python基础知识之装饰器decorator
- 5 Python-装饰器
- python装饰器装饰类
- [python]python装饰器
- 【脚本语言系列】关于Python基础知识装饰器,你需要知道的事
- Python学习---第5天---装饰器
- python知识点(5)-----------装饰器小结
- Python装饰器学习
- Python装饰器
- python 装饰器
- Python装饰器
- python 装饰器 应用
- python 装饰器2
- Python装饰器学习
- python装饰器
- python装饰器
- python 装饰器入门
- Python基础知识2:字典
- 跟我一起写Makefile
- Bundle Adjustment学习
- 单选按钮居中
- Python基础知识6:格式化字符、颜色
- Python基础知识:5:装饰器
- [分享]Kotlin 教程
- Mac下快速搭建PHP开发环境,Apache,Nginx,MySQL
- Linux存储在线管理(一)FC磁盘设备管理
- HTML5调用手机摄像头拍照
- 机器学习教材中的 7 大经典问题
- github+hexo搭建博客
- 软件开发常用网站
- Python基础知识3:函数、三元函数、lambda函数