Python核心编程 | 浅谈闭包的使用

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):
    print('---1---')   # 1
    def test_in():   #2 只定义 「内」函数 没被执行
      print(number+100)
      print('---2---')
    print('---3---')   #3
    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.因为闭包引用了外部函数的变量, 外部函数的局部变量没有被及时释放,消耗内存。
相关文章
相关标签/搜索