函数的闭包

闭包

定义:这个函数首先是一个嵌套函数,且这个函数调用了外部的函数变量。两个条件缺一不可

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

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2019-01-16 22:51  舒畅123  阅读(146)  评论(0)    收藏  举报