Python闭包相关知识点(作者的python环境是python3.8)

一、什么是闭包
简单来讲,就是python中内部函数对外部函数的局部变量进行了引用,这个内部函数就叫做闭包。
举个例子:

def func():
    a = 1
    def func1(num):
        print(num + a)
    return func1
exp1 = func()
exp1(1)

在这块代码中,内部函数func1引用了外部函数func的变量a,在这种情况下,内部函数func1就叫做闭包。

二、闭包的意义
在将闭包的意义之前,让我们先来了解几个知识点:
1、函数内东西的生存周期:函数内的东西只有在函数运行期间才能存活。
2、python运算符==is的区别:
1)==表示两个变量的内容是否相等(变量的值是否一致)
2)is表示两个变量是否是同一个东西(变量的地址是否一致)

好,我们继续

def func():
    a = 1
    def func1(num):
        print(num + a)
    return func1
exp1 = func()
exp1(1)

还是拿这块代码做例子,变量exp1被func()函数赋值,由于func()返回值是一个函数,因此变量exp1相当于func1(),exp1 = func()这行代码结束后,func()函数执行完后消失,里面的内容消失,变量a本应该消失,但因为最终返回了func1()函数(这个返回的函数给了变量exp1),导致变量a随着返回的函数一起延续了下来,即变量exp1消失后,局部变量a才消失。
所以,闭包的意义就是:延长外部函数内局部变量的生命周期。

三、闭包与内存的一些事
让我们再了解几个知识点:
1)python中不同变量指向相同的值(比如整形数1,列表),这些变量地址一致。
2)一个函数对应一片内存空间(函数就是线程,每个函数(每个线程)都会在内存中维护一片自己的栈空间)。
3)(这点是与本博文不相干的)进程是资源分配的最小单位,线程是独立调度的最小单位。同一个进程中的多个线程之间可以并发执行,他们共享进程资源。
4)函数名就是这个函数的入口地址

上代码:

def test1():
    a = 1
    def f():
        print('hello')
    return f

x = test1()
y = test1()
print(x()==y())
print(x==y)

最终的结果为:hello hello True False

验证内外函数局部变量地址的代码(值不同,变量地址不同):

def test1():
    a = 1
    print(id(a))#id()为查看一个变量地址的方法
    def f():
        a = 2
        print(id(a))
    return f

x = test1()
x()

注意,只有添加了x()才能执行f()函数里面的内容(不添加的话,内部函数没有实例化)
这段代码执行后,两个a地址不一样

来个猛的:

def test1():
    a = 1
    print(id(a))#id()为查看一个变量地址的方法
    def f():
        a = 2
        print(id(a))
    return f

x = test1()
x()
y = test1()
y()

这时候你会发现,虽然两个函数的空间在内存中位置不一致,但由于python是按值分配内存空间。这导致值相同,内存空间相同
这是执行结果:(第一个地址值与第三个地址值一致,虽然变量属于不同函数,但指向相同内存空间,二四同理)

140718125752064
 140718125752096
 140718125752064
 140718125752096

再看个例子吧:

python 闭包函数原理 python闭包详解_内存空间

四、关于闭包的常见错误
详情见这篇文章:https://zhuanlan.zhihu.com/p/22229197

五、总结
闭包其实就是一个可以赋值给外部函数外的变量的一个内部函数。