python 学习汇总53:闭包(中级学习- tcy)
发布日期:2021-06-29 14:47:15 浏览次数:2 分类:技术文章

本文共 3074 字,大约阅读时间需要 10 分钟。

闭包的定义,及基本概念;实例;闭包定义中的典型错误分析及解决办法;闭包在实践的应用。 

闭包                 创建时间:2018/8/11  修改时间:2018/11/18

 1.定义: 

闭包:是由函数及其相关的引用环境组合而成实体(即:闭包=函数+引用环境)内部函数引用外部作用域(非全局)变量,会把引用环境和函数体打包成一个整体(闭包)返回,内部函数被认为是闭包(closure).函数:可作另一个函数参数或返回值,赋给变量。函数可嵌套定义;每次调用ExFunc函数返回新闭包实例,实例之间是隔离;一个函数可返回一个计算结果或函数。返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量引用环境指在程序执行中的某个点所有处于活跃状态的约束(变量名字和其所代表的对象之间的联系)所组成的集合。  

2.实例:

def ExFunc(n): # 函数返回的就是闭包   sum = n   def InsFunc(): # 内嵌函数是闭包     return sum + 1 # 引用到外层函数中的局部变量sum   return InsFunc # 返回值是函数myFunc = ExFunc(10) # 返回新闭包实例a1 = myFunc()    # 11myAnotherFunc = ExFunc(20) # 返回新闭包实例a2 = myAnotherFunc()    # 21print(a1, a2)实例2def add(x):  def adder(y):    return x + y  return addera = add(8)b=addtype(a)    #
a.__name__ #'adder'a(10) #18b(8)(10) #182.使用闭包注意事项: 
2.1.闭包中不能修改外部作用域局部变量实例1:-每次调用闭包函数时都对变量a进行递增的操作#使用闭包时经典错误代码def foo():  a =    1   def bar():    # nonlocal a    a = a + 1 #修改外部作用域局部变量    #python规则指定所有在赋值语句左面的变量都是局部变量    return a   return barc = foo()print(c()) #错误#解决方法def foo():  a = [1]  def bar():    a[0] = a[0] +    1    return a[0]  return bar
 2.2. 循环结束循环体中临时变量i不会销毁存在于执行环境中:注意:1)返回闭包时:返回函数不要引用任何循环变量,或后续会发生变化变量。2)如要引用循环变量方法1:该函数创建一个参数,用这个参数绑定到循环变量 ;如实例  1方法2:迭代 方法;参见实例   2再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变

 实例2: 

#python的函数只有在执行时,才会去找函数体里的变量的值。lst = []for i in range(3):   def foo(x):     print (x + i)   lst.append(foo)for f in lst:   f(2) #4,4,4#解决方法for i in range(3):   def foo(x,y=i):     print( x + y)   lst.append(foo)  

 实例3 : 

def  count():   lst = []   for i in range(1, 4):     def f():       return i*i     lst.append(f)       return lstf1, f2, f3 = count()f1(),f2(),f3() #9,9,9#解决办法def count():   def f(j):     def g():       return j*j     return g   lst = []   for i in range(1, 4):      lst.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()      return lst#  结果:f1, f2, f3 = count()f1(),f2(),f3() #1,4,9

 3.作用

闭包主要是在函数式开发过程中使用。
用途1 

当闭包执行完后,仍然能够保持住当前的运行环境。希望函数每次执行结果基于这个函数上次的运行结果。例棋盘游戏:棋盘大小为50*50,左上角为坐标系原点(0,0),我需要一个函数,接收2个参数,分别为方向(direction),步长(step),该函数控制棋子的运动。棋子运动的新的坐标除了依赖于方向和步长以外,当然还要根据原来所处的坐标点,用闭包就可以保持住这个棋子原来所处的坐标。origin = [0, 0] # 坐标系统原点legal_x = [0, 50] # x轴方向的合法坐标legal_y = [0, 50] # y轴方向的合法坐标def create(pos=origin):   def player(direction,step):      # 先判断参数direction,step合法性,direction不能斜走step不能为负      # 对新生成的x,y坐标合法性判断处理,      new_x = pos[0] + direction[0]*step      new_y = pos[1] + direction[1]*step      pos[0] = new_x      pos[1] = new_y #注意!此处不能写成 pos = [new_x, new_y]      return pos   return playerplayer = create() # 创建棋子player,起点为原点print player([1,0],10) # 向x轴正方向移动10步print player([0,1],20) # 向y轴正方向移动20步print player([-1,0],10) # 向x轴负方向移动10步输出:[10, 0][10, 20][0, 20]

 用途2: 

闭包可以根据外部作用域的局部变量来得到不同的结果,这有点像一种类似配置功能的作用,我们可以修改外部的变量,闭包根据这个变量展现出不同的功能。比如有时我们需要对某些文件的特殊行进行分析,先要提取出这些特殊行。
def make_filter(keep):    def the_filter(file_name):        file = open(file_name)        lines = file.readlines()        file.close()        filter_doc = [i for i in lines if keep in i]        return filter_doc        return the_filter    # 取得文件"result.txt"中含有"pass"关键字的行filter = make_filter("pass")filter_result = filter("result.txt")

 

转载地址:https://chunyou.blog.csdn.net/article/details/84204184 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:python 学习汇总54:operator模块(全 推荐- tcy)
下一篇:python 学习汇总52:迭代器常用内置函数map,filter,zip,reduce(入门学习- tcy)

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月21日 21时58分07秒