预习
在学习闭包之前,我们先要弄懂一件事儿。
同理:
Test其实就是一个变量,变量中存放着函数体的地址,就像a变量中存放着100的地址一样。
t = Test实质上就是浅拷贝行为。将变量Test中的地址存放到变量t中
我们如果要调用Test函数,Test()
当t获取了函数体的地址后,同样可以以t()的形式调用函数
!!!注意:这里可以结合之前的深拷贝浅拷贝知识。验证一些东西。
如果对深浅拷贝不太了解,可以自行百度,或者移步
Python学习笔记——深拷贝与浅拷贝(可能讲的比较乱)
请看下图:
这里我深拷贝了Test,发现拷贝完了以后s和Test的id也就是里面存放着地址是相同的。根据之前的知识点,在进行深拷贝时,当地址对应的空间中存放着不可变类型数据的时候,自动转换为浅拷贝。
由此可知,函数体本身就是不可变数据类型。
闭包
了解以上机制以后接下来我们来看今天的内容——闭包
先看一段代码:
闭包是什么?
一个函数体内还有另外一个函数体,内函数体中用到了外函数体的变量,这时候我们就称内函数是一个闭包。
就像上面代码中写的一样,内函数体Test_in中用到了外函数体Test中的变量num
所以我们称Test_in是闭包。
仔细观察代码,结合我们刚才的预习,写出下列结果/含义:
t = Test
t1 = t(100)
t2 = Test(100)
t(100)(50)
t1(50)
下面我们依次解析一下
t = Test 在我们预习的时候就讲过了,其实是把Test所对应的函数体的地址给了t(浅拷贝)
t1 = t(100)和t2 = Test(100) 因为t和Test指向同一个函数体,所以调用函数的时候是相同的结果,都是返回Test_in的函数体的地址(此时函数体内num为100)。
t(100)(50)和t1(50) 与前面原理一样。t(100)所对应的就是函数体内num为100是Test_in函数体的地址,t1也是,这两个代表着当num为100时,调用Test_in(50)
结果如下:
总结
如果上面的东西你都看懂了。那就结合之前学过的知识,看看能不能得出什么结论?
闭包是个函数体,所以也是属于不可变数据类型。对其进行深拷贝,也等同于浅拷贝。(验证预习中的结论)
闭包的应用,本来我们要传三个数算出一个结果,利用闭包,可以保留那些不需要更换的数字,直接传入需要替换的数字即可,而且可以重复利用。