装饰器
[toc]
一、闭包
(一)什么是闭包
-
闭包:内层函数调用外层函数的变量就是闭包(不能是全局变量)
def func1():a = 10def func2():print(a) # 内层函数调用外层函数的变量,这就是一个闭包func1() -
检测闭包的方法
函数名.__closure__- 若返回对象地址就是一个闭包,返回None就不是一个闭包
- 注意:
.__closure__检测的是函数名,判断这个函数是否是闭包
def func1():a = 10def func2():print(a) # 调用外层变量a,是闭包print(func2.__closure__) # 判断func2是否是闭包func1()运行结果:(<cell at 0x00000230F21874F8: int object at 0x0000000063258190>,)def func1():a = 10def func2():a = 10print(a) # 使用自身函数变量a,不是闭包print(func2.__closure__)func1()运行结果:None -
如何在全局空间中调用内部函数
- 外层函数返回内层函数的函数名(内存地址),就可在全局空间中调用内部函数
def func1():a = 10def func2():print(a)return func2 # 返回内层函数的函数名f = func1() # 此时f就是func2f() # 调用内层函数func2print(f.__closure__)运行结果:10(<cell at 0x00000280A87574F8: int object at 0x0000000063258190>,)
(二)闭包的作用
- 保护数据安全
- 说白话一点 ,如果数据放在全局变量中(顶格写代码),数据的安全性很低,因为所有人都可以无意间修改它,想解决这个问题我们可以把数据放到函数中,只要不调用这个函数,我的数据就是安全的。但是有个问题,每次执行函数完,解释器就会自动清空此函数开辟的局部空间中所有内容(包括数据开辟的空间),所以每次调用完函数,我的数据就没了,此时就需要利用到了闭包。闭包可以在内层函数调用外层函数中的变量,而且内层函数如果调用了外层函数中的变量,那这个变量将不会消亡,将会常驻内存。所以,我们只需要在全局空间中调用这个闭包的内层函数,就可以使用我的数据了,而且数据的安全性也提高了。
-
将变量常驻内存,供后续代码使用
def outer():lst = [1,2,3,4,5]def inner():return lstreturn innerf = outer()f_lst = f()print(f_lst)运行结果:[1,2,3,4,5]
(三)闭包的应用
- 防止数据被误修改
- 装饰器(与闭包格式相同)