函数的闭包
闭包
定义:这个函数首先是一个嵌套函数,且这个函数调用了外部的函数变量。两个条件缺一不可
def outer(): a=1 def inner():#inner是一个嵌套函数 print(a)#inner作为内部函数调用了外部函数变量a print(inner.__closure__)#通过打印函数名.__closure__根据结果可以判断这个函数是不是一个闭包 outer() print(outer.__closure__) D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/14.py (<cell at 0x000002BBAD210108: int object at 0x00007FFE5D44EF00>,)#结果中出现了cell,就表示这个函数是一个闭包 None#outer函数不是一个闭包函数,所以结果为none Process finished with exit code 0
闭包的精妙之处
def outer(): a=1 def inner(): print(a) inner()#如果要运行inner这个函数 outer()
如果我想要调用inner函数,那么就必须通过outter函数来调用,那么频繁的待用inner函数,那么在就相当于outter中的变量a不停的被写入内存,然后随着程序的结束而被擦除;再次被写入,擦除,在程序的执行过程中会浪费大量时间
那么可以利用函数名本质上就是内存地址,可以被作为参数返回这一特性,修改代码如下
1 def outer(): 2 a=1 3 def inner():#inner是一个嵌套函数 4 print(a)#inner作为内部函数调用了外部函数变量a 5 return inner#返回inner,注意这里的return和def inner左对齐 6 inn=outer()#将inner的返回值传给outer,外部的outter函数开始运行;这个代码的本质是将inner这个函数名的内存地址传给inn, 7 inn()#这里inn是一个全局变量,也就说将局部变量inner通过这一些列操作变成了一个全局变量;本质是inner函数的内存地址+()函数开始运行
注意上面函数精妙之处在于:将内部的inner函数传到外面来运行,且内部inner函数要用到外部函数的变量a,那么外部函数的局部变量a会一直保存在内存中不会消失,直至整个程序结束。也就是说当不使用inner函数的时候,这个a不会消失而会一直保存在内存中,节省程序的运行时间。
其次:对于变量a而言,变量a是一个局部变量,不是一个全局变量,通过上面的操作以后,变相的将a变成了一个只是针对inner函数而言的全局变量,随时都可以用.
闭包的一个简单应用
# url='http://www.meizitu.com/' # ret=urllib.request.urlopen(url).read() # print(ret) import urllib.request def func_url(): url = 'http://www.meizitu.com/' def get(): ret = urllib.request.urlopen(url).read() print(ret) return get get_func=func_url() get_func()
这里get函数就是闭包,url就是变量
自己对闭包的一些感悟
还是引用刚开始时的例子
def outer(): a=1 def inner(): print(a) inner()#如果要运行inner这个函数 outer()
开始修改
def outer(): a=1 def inner(): print(a) # return inner inner() print(inner()) outer() D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/14.py 1 1 None Process finished with exit code 0
可以看到结果中有两个1,其中第一个1是在执行inner()时候出现的,第二个1是print括号中的inner()被执行的时候出现的,当执行print(inner())的时候由于上面的return inner没有被执行,所以没有返回值,所以结果是none.
当执行return这行代码的时候
def outer(): a=1 def inner(): print(a) return inner inner() print(inner()) outer() D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/14.py 1 1 <function outer.<locals>.inner at 0x00000197767C20D0> Process finished with exit code 0
print(inner())出现了执行结果,执行结果为内存地址
进阶
1 def outer(): 2 a=1 3 def inner(): 4 print(a) 5 return inner 6 # inner() 7 print(inner())#根据return的性质,return后面和其左对齐的代码都不会被执行,也就是说print(inner())这行代码没有被执行 8 print(outer()) 9 outer()#由于使用return inner后,就相当于outer()=inner,所以outer不会执行 10 # print(outer()()) 11 outer()()#outer()再加上一个括号以后就表示改函数被执行了,且执行结果是1 12 print(outer().__closure__) 13 14 15 D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/14.py 16 <function outer.<locals>.inner at 0x000001E1F5CF20D0> 17 1 18 (<cell at 0x000001E1F3CC0108: int object at 0x00007FFE6280EF00>,) 19 20 Process finished with exit code 0