【1】前置知识储备
详细参考上一篇博文:https://www.cnblogs.com/gered/p/13954411.html#autoid-1-3-0
【1.1】函数即变量
在数字、字符串变量中,我们之前的数据类型文章中就说了,它是不可以修改的,因为它是放在内存堆中。如果修改就是新赋值,就是在内存堆中重新开辟了一个字符串/数字,然后把变量指向它;
字符串举例:
如果有 x=1,y=x,那么这个时候, x 和 y都是引用指向 1 的内存地址,x 如果修改不影响 y。
那么这个内存中的1什么时候被回收呢? 当该内存存储地址没有被任何变量、函数等引用指向的话,就会随着python默认的刷新检测机制检测发现没有任何引用,就会把它回收掉:
函数同理:
那么同理,函数名也是一个引用指针,指向内存中存储函数体的这一块地址。这个我们从匿名函数形式 就可以比较直观的看出来;
【1.2】高阶函数
(1)把函数名做实参传给另外一个函数的形参(这也就表达了,高阶函数可以在不修改被装饰函数代码的情况下,为其添加功能)
(2)返回值中包含函数名(不修改函数的调用方式的情况下,为其添加功能)
【1.3】嵌套函数
嵌套函数,就是在函数的内部用def 定义另外的函数
【2】装饰器:基本形式(就是高阶函数+嵌套函数)
装饰器:本质上是函数,是用来装饰其他函数的(就是为其他函数添加附加功能)
原则(1):不能修改被装饰的函数的源代码
原则(2):不能修改被装饰的函数的调用方式
即:装饰器对函数来说是完全透明的,就是说函数感知不到装饰器的存在,也就函数的源代码和调用方式都没有被改变
(1)好理解的形式(无参数)
import time def test1(): time.sleep(3) print('in the test1') def test2(): time.sleep(3) print('in the test2') def timer(func): # timer(test1) func=test1 def deco(): start_time=time.time() func() # run test1() stop_time=time.time() print('run the fun used {} second'.format(stop_time-start_time)) return deco test1 = timer(test1) test1()
in the test1
run the fun used 3.0009162425994873 second
~~~实现了不修改函数源代码,也不修改函数调用方式,添加了新功能 输出函数执行使用时间
(2)语法糖:即用 @装饰器名 放到函数定义的上一行(带参数)
不带参数的函数也可以用 这种装饰器
import time def timer(func): def warpper(*args,**kwargs): start_time=time.time() func(*args,**kwargs) stop_time=time.time() print('the func run time is {} '.format(stop_time-start_time)) return warpper
@timer # 这里实现了 test1 = timer(test1) 的功能 def test1(a,b,c): time.sleep(3) print('this is test1!')
print(a,b,c)
test1(1,2,3)
this is test1!
the func run time is 3.000502824783325
(3)返回值的参数
import time user, passwd = 'gg', '123456' def auth(func): def wrapper(*args, **kwargs): username = input("Username:").strip() password = input("Password:").strip() if user == username and passwd == password: print("