1.函数的引用
>>> def test(): print('test:') >>> test <function test at 0x10ffad488> >>> myfun=test >>> myfun() test: >>>
函数名实际上指向函数体的内存区域,所以输出函数名时为:
<function test at 0x10ffad488>
若myfun=test,此时
变量 myfun 也指向了该内存区域,所以可以通过 test() 调用函数,也可以通过 myfun() 调用
这种情况,在C 、C++中类似 函数指针
2.什么是闭包?
在函数内部定义一个函数,并且这个函数用到外边函数的变量,这个函数以及用到的变量
统称为闭包
如:
>>> def test(number): print('---1---') def test_in(): print(number+100) print('---2---') print('---3---') return test_in() >>> test(2) ---1--- ---3--- 102 ---2--- >>>
定义一个函数 test() ,在函数内部定义另一个函数 test_in()
test_in()又使用到了 外部函数 的变量,此时,test_in()和
被使用到的变量,统称为闭包
>>> def test(number): def test_in(): #2 只定义 「内」函数 没被执行 print(number+100) print('---2---') return test_in() #4 在return 语句,调用「内」函数
3.闭包的应用
如:
>>> def test(number): def test_in(): print(number+100) return test_in >>> ref=test(11) >>> ref() 111 >>>
在 外部函数 内定义了 内部函数, 内部函数又使用了 内部函数的变量
外部函数返回了内部函数的地址:return test_in
此时 ref=test(11) ,使得ref得到了 test_in()的引用
于是可以通过 ref() 直接调用函数,虽然test_in使用了外部函数test()的变量number
但接下来每次调用ref() 都可以直接调用,外部函数变量number不被释放
>>> ref() # ref() 俨然如同一个独立函数了 111 >>> ref() 111 >>> ref() 111 >>>
4.外边函数被保留
外部函数虽然只调用了一次,但它不能被销毁,原因是内部函数还需要使用到它的变量,若该函数被销毁,则内边函数将无法被正常调用
ref() 之所以能够被反复调用,一方面在于调用外部函数test()时将test_in()的地址赋值给ref变量,这只让ref指向了函数体,能够以ref()的方式被调用,
而另一方面,当内部函数体被调用时,不能够出错,所以需要保留它需要用到的外部变量,因此number变量必须存在,test函数就必须保留。
闭包的一个特点:外部函数返回 内部函数的一个引用
5.闭包的一个应用实例:
>>> def test(a,b): def test_in(x): print(a*x+b) return test_in ''' 在调用test时,传递了a,b;实际上直线已经被确定,所以以下 line1和line2中直接传个值就可以了。 ''' >>> line1=test(2,5) >>> line1(1) 7 >>> line2=test(3,4) >>> line2(2) 10 >>>
在这个例子中,函数test_in和变量a,b构成闭包。
我们只需要通过变换a,b的值,就可以确定一条不同的直线(y=2x+5 / y=3x+4)
由此,闭包具备提高代码复用性的作用
如果没有闭包,我们需要每次创建直线函数时,同时说明a,b,x,这样需要更多的函数传递
而且减少了代码的可移植性:
>>> def line(a,b,x): print(a*x+b) >>> line(1,1,1) 2 >>> line(2,2,2) 6 >>>
每次都需要传递a,b,x的值,而使用闭包的话,a,b可以只写一次,让调用过程简化
6.如图:重新开辟空间
Python解释器在处理闭包时,由于line1=test(1,1) 调用了test,此时test没有被释放,依然占用着内存;
在处理line2=test(2,2)时,不会覆盖到原先执行line1=test(1,1)时test的内存,也就是说不会改变
原先a=1,b=1的test,而是会新申请一块内存,执行「新」test,再保存a=2,b=2
7.闭包的思考
1.优化了变量
2.由于闭包引用了外部函数的变量,外部函数的局部变量没有被及时释放,消耗内存。