博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python之路【第四篇】:Python基础(19)——装饰器
阅读量:7194 次
发布时间:2019-06-29

本文共 6929 字,大约阅读时间需要 23 分钟。

#普通装饰器 # (@+函数名),需要记住关键两点: #功能: #1、自动执行outer函数,并且将其下面的函数名f1当作参数传递 #2、将outer函数的返回值,重新赋值给f1 # #装饰器必备 # ####第一:函数名和执行函数#### # def foo(): #创建函数 # print('hello') #函数体 # foo #表示是函数名,代指整个函数 # foo() #表示执行f00函数 # # 输出:hello # ####第二:函数被重新定义### # def foo(): # print("foo1") # # foo = lambda : print("foo2") #lambda表达式,无参数 # # foo() #执行下面的lambda表达式,而不是原来的foo函数,foo函数已经被重新定义 # #同名函数被覆盖 # def f1(): #1 # print(123) # # def f1():#2 #4 # print(456) #5 # f1() #3 # #输出: 456 #f1函数作为参数进行传递 # def f1(): #1 创建f1函数 #6执行f1()函数,结果是打印输出123 # print("123") #7 # #没有return,默认返回None # def f2(xxx): #2 创建f2函数 #4 接收到传递的f1以后,xxx也是代指f1函数的整体,f2(xxx)就相当于f2(f1) # ret = xxx() #5 xxx()就等于是f1(),f1()就代表去执行f1()这整个函数。 # # f2(f1) #3 调用f2函数,f1作为参数(f1没有单引号和双引号是一个函数名; f1没有带括号(),代指的是f1函数的整体,f1作为参数传递给xxx # #装饰器 流程剖析 分解功能1:自动执行outer()函数,并将下面的函数名f1作为参数传递 () # # def outer(): #TypeError: outer() takes 0 positional arguments but 1 was given 翻译:outer需要0个参数,但传递了1个参数 # def outer(func): #1在内存中创建outer函数 #3执行outer(f1)函数 #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。 # print(123) #4 执行函数体:打印123 # print(func) #5 执行函数体:打印func参数,输出:
# @outer #2 自动执行outer()函数,并将下面的函数名f1作为参数传递。即@outer等价于outer(f1) # def f1(): # print("F1") # #装饰器 流程剖析 分解功能2:将outer函数的返回值111,重新赋值给f1 # def outer(func): #1在内存中创建outer函数 #3执行outer(f1)函数 #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。 # return "111" #4 将outer函数的返回值111,重新赋值给f1。 # @outer #2 自动执行outer()函数,并将下面的函数名f1作为参数传递 # def f1(): # print("F1") # print(f1) #5 原来的f1函数被覆盖,被重新赋值为111. #问题解析: #4 (为什么outer函数的返回值111,就重新赋值给了f1,f1并没有调用outer(f1)函数啊?)这个问题纠结了我至少4个小时。感谢绍宁指点。如下: # @outter 等价于 outter(f1) # 等价于f1=outter(f1) # outter函数的返回值是111 # 所以f1就变成了111 # 装饰器就是在把原来的函数包起来加工一下,但是加工后还是叫原来的函数名,用了装饰器后 原来的函数名 等于装饰器函数的返回值 # 参考链接:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html # #函数是一个对象,可以赋值给其他对象变量,通过变量可以调用该函数。 # def foo(): # print("test") # f = foo #注意没有使用圆括号,因为不是在调用函数 # f() # # # 输出:test # print(foo.__name__)#通过函数对象_name_属性,可以拿到函数的名字: # #输出:foo # print(f.__name__) # # 输出:foo #装饰器 流程剖析 将outer函数的返回值,换成其他函数。 #注:解释器解释后f1函数就等于111,这样f1函数就被成功修改了,那以后外部再来调用f1函数的时候就会调用111,那我们就成功的将f1函数换成了111 #我们能把f1换成111,同理,也能换成一个其他函数。 # def outer(func): #1在内存中创建outer函数 #3执行outer(f1)函数 #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。 # # return "111" #4 将outer函数的返回值111,重新赋值给f1。 # def inner(): #4 在内存中创建inner函数 #8 外部调用f1()函数就等于是调用inner函数,f1函数换成了inner函数,即新f1函数。 # print("在执行老的f1函数之前执行命令") #9 在执行老的f1函数之前执行 # func() #10 第2步时,f1函数作为参数传递给了outer函数的func参数,func代指的就是老的f1函数,即装饰的原函数,func加括号,代表执行老的f1()函数 # print("在执行老的f1函数之后执行命令") #11 在执行老的f1函数之后执行 # return inner #5 inner不加括号代指的是整个inner函数,将outer函数的返回值inner函数,重新赋值给f1,f1就代指的是inner函数。 # #inner()加括号是执行inner函数,代表的是return之前先执行inner函数,然后把返回值(默认为None)赋值给f1,把inner函数 # #执行后的返回值赋值给f1,外部程序再调用时得到的是inner的返回值,不是f1的返回值,这样做会破坏f1函数原有的功能 # # @outer #2 自动执行outer()函数,并将下面的函数名f1作为参数传递 # def f1(): # print("F1") # # print(f1) #6 原来的f1函数被覆盖,被重新赋值为inner函数。#
.inner at 0x00000000030AF1E0> # #装饰器 流程剖析 返回值 # #注:解释器解释后f1函数就等于111,这样f1函数就被成功修改了,那以后外部再来调用f1函数的时候就会调用111,那我们就成功的将f1函数换成了111 # #我们能把f1换成111,同理,也能换成一个其他函数。 # def outer(func): #1在内存中创建outer函数 #3执行outer(f1)函数 #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。 # # return "111" #4 将outer函数的返回值111,重新赋值给f1。 # def inner(): #4 在内存中创建inner函数 #8 外部调用f1()函数就等于是调用inner函数,f1函数换成了inner函数,即新f1函数。 # print("在执行老的f1函数之前执行命令") #9 在执行老的f1函数之前执行 # # ret = func() #10 第2步时,f1函数作为参数传递给了outer函数的func参数,func代指的就是老的f1函数,即装饰的原函数,func加括号,代表执行老的f1()函数 # r = func() #10 执行func()函数,等于执行原f1()函数,原f1函数有返回值,定义变量r用于接收原f1函数的返回值 # print("在执行老的f1函数之后执行命令") #11 在执行老的f1函数之后执行 # return r #12 r代表原f1函数的返回值,新f1函数执行之后将原f1函数的返回值返回给函数调用者。(函数遇到return就不再向下执行,所以把return放在最下面) # return inner #5 inner不加括号代指的是整个inner函数,将outer函数的返回值inner函数,重新赋值给f1,f1就代指的是inner函数。 # #inner()加括号是执行inner函数,代表的是return之前先执行inner函数,然后把返回值(默认为None)赋值给f1,把inner函数 # #执行后的返回值赋值给f1,外部程序再调用时得到的是inner的返回值,不是f1的返回值,这样做会破坏f1函数原有的功能 # # @outer #2 自动执行outer()函数,并将下面的函数名f1作为参数传递 # def f1(): # print("F1") # return "原f1函数返回值FFFF" #原f1函数有返回值FFFF # # print(f1) #6 原来的f1函数被覆盖,被重新赋值为inner函数。#
.inner at 0x00000000030AF1E0> # #装饰器 流程剖析 1个参数 # #注:解释器解释后f1函数就等于111,这样f1函数就被成功修改了,那以后外部再来调用f1函数的时候就会调用111,那我们就成功的将f1函数换成了111 # #我们能把f1换成111,同理,也能换成一个其他函数。 # def outer(func): #1在内存中创建outer函数 #3执行outer(f1)函数 #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。 # # return "111" #4 将outer函数的返回值111,重新赋值给f1。 # def inner(a): #4 在内存中创建inner函数 #8 外部调用f1()函数就等于是调用inner函数,f1函数换成了inner函数,即新f1函数。#8.1外部调用新f1函数的实参,首先传递给形参“a” # print("在执行老的f1函数之前执行命令") #9 在执行老的f1函数之前执行 # # ret = func() #10 第2步时,f1函数作为参数传递给了outer函数的func参数,func代指的就是老的f1函数,即装饰的原函数,func加括号,代表执行老的f1()函数 # r = func(a) #10 执行func()函数,等于执行原f1()函数,原f1函数有返回值,定义变量r用于接收原f1函数的返回值 #10.1将函数调用者传递的参数传递给原f1()函数。 # print("在执行老的f1函数之后执行命令") #11 在执行老的f1函数之后执行 # return r #12 r代表原f1函数的返回值,新f1函数执行之后将原f1函数的返回值返回给函数调用者。(函数遇到return就不再向下执行,所以把return放在最下面) # return inner #5 inner不加括号代指的是整个inner函数,将outer函数的返回值inner函数,重新赋值给f1,f1就代指的是inner函数。 # #inner()加括号是执行inner函数,代表的是return之前先执行inner函数,然后把返回值(默认为None)赋值给f1,把inner函数 # #执行后的返回值赋值给f1,外部程序再调用时得到的是inner的返回值,不是f1的返回值,这样做会破坏f1函数原有的功能 # # @outer #2 自动执行outer()函数,并将下面的函数名f1作为参数传递 # def f1(arg): #10.2接收函数调用者传递的参数arf = a # # print("F1") # print(arg) # return "原f1函数返回值FFFF" #原f1函数有返回值FFFF # # print(f1) #6 原来的f1函数被覆盖,被重新赋值为inner函数。#
.inner at 0x00000000030AF1E0> #注:解释器解释后f1函数就等于111,这样f1函数就被成功修改了,那以后外部再来调用f1函数的时候就会调用111,那我们就成功的将f1函数换成了111 #我们能把f1换成111,同理,也能换成一个其他函数。 # def outer(func): #1在内存中创建outer函数 #3执行outer(f1)函数 #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。 # # return "111" #4 将outer函数的返回值111,重新赋值给f1。 # def inner(a): #4 在内存中创建inner函数 #8 外部调用f1()函数就等于是调用inner函数,f1函数换成了inner函数,即新f1函数。#8.1外部调用新f1函数的实参,首先传递给形参“a” # print("在执行老的f1函数之前执行命令") #9 在执行老的f1函数之前执行 # # ret = func() #10 第2步时,f1函数作为参数传递给了outer函数的func参数,func代指的就是老的f1函数,即装饰的原函数,func加括号,代表执行老的f1()函数 # r = func(a) #10 执行func()函数,等于执行原f1()函数,原f1函数有返回值,定义变量r用于接收原f1函数的返回值 #10.1将函数调用者传递的参数传递给原f1()函数。 # print("在执行老的f1函数之后执行命令") #11 在执行老的f1函数之后执行 # return r #12 r代表原f1函数的返回值,新f1函数执行之后将原f1函数的返回值返回给函数调用者。(函数遇到return就不再向下执行,所以把return放在最下面) # return inner #5 inner不加括号代指的是整个inner函数,将outer函数的返回值inner函数,重新赋值给f1,f1就代指的是inner函数。 # #inner()加括号是执行inner函数,代表的是return之前先执行inner函数,然后把返回值(默认为None)赋值给f1,把inner函数 # #执行后的返回值赋值给f1,外部程序再调用时得到的是inner的返回值,不是f1的返回值,这样做会破坏f1函数原有的功能 # # @outer #2 自动执行outer()函数,并将下面的函数名f1作为参数传递 # def f1(arg): #10.2接收函数调用者传递的参数arf = a # # print("F1") # print(arg) # return "原f1函数返回值FFFF" #原f1函数有返回值FFFF # # print(f1) #6 原来的f1函数被覆盖,被重新赋值为inner函数。#
.inner at 0x00000000030AF1E0> #装饰器 流程剖析 函数传递多个参数使用万能参数,*args,**kwargs def outer(func): #创建outer函数;f2函数作为参数传递给outer函数,func代指装饰的原函数,即原f2函数。 def inner(*args,**kwargs): #创建嵌套的inner函数,a,b接收f2函数调用者传递的参数 #*args,**kwargs可以接收任意参数 # pass print("before:执行原函数之前") r = func(*args,**kwargs) #执行原函数,接收原函数返回值;a,b将调用者传递的参数传递给原f2函数。#python自动把*args,**kwargs里面的参数传递给原函数 print("after:执行原函数之后") return r #返回原函数返回值 return inner #将inner函数的返回值重新赋值给f2函数,inner函数即为新f2函数。(inner后面无括号)@outerdef f1(): print("F1") return "f1"@outerdef f2(a1,a2): print(a1,a2) return "f2"

转载于:https://www.cnblogs.com/jiangnanmu/p/5558043.html

你可能感兴趣的文章
分享一段js,判断是否是在iPhone中的Safari浏览器打开的页面
查看>>
ubuntu11.10 搭建lnmp服务器
查看>>
Python学习【第22篇】:线程理论基础
查看>>
在servlet连接mysql下的最简单增删查改
查看>>
第15章 套接字
查看>>
.Net Attribute详解(上)-Attribute本质以及一个简单示例
查看>>
leetcode------Same Tree
查看>>
c++第五次实验报告
查看>>
laravel 项目 配置 nginx
查看>>
POJ-1797 Heavy Transportation(最大生成树)
查看>>
BZOJ-1407: [Noi2002]Savage (扩展欧几里得)
查看>>
Android快捷便利但不常被使用的原生工具类
查看>>
第三章 生存期模型
查看>>
UNIX网络编程——客户/服务器程序设计示范(六)
查看>>
spring+struts2+spring_jdbc框架的集成
查看>>
javascript string类常用方法整理
查看>>
ViewState的用法
查看>>
Xcode7工程改名
查看>>
oc调用swift的打包.a / framework 不成功?!
查看>>
快速排序
查看>>