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
再看个例子吧:(这个例子来自图片中的这位up主)
四、关于闭包的常见错误
详情见这篇文章:https://zhuanlan.zhihu.com/p/22229197
五、总结
闭包其实就是一个可以赋值给外部函数外的变量的一个内部函数。