闭包python 菜鸟教程,python 闭包函数

  闭包python 菜鸟教程,python 闭包函数

  (如转载,请注明出处,谢谢。)

  许多语言中都涉及到闭包的概念。本文主要讲python中的闭包。Python中使用的闭包主要用于功能开发。

  一,定义

  python中的闭包是用表达式来定义(解释)的:如果在内部函数中引用了外部作用域(而不是全局作用域)中的变量,那么内部函数就被认为是闭包。这个定义比较直白,容易理解,不像其他定义那么迂腐(那些迂腐的解释都是在解释一个名词的过程中充满了人。这里有一个简单的例子来说明。def addx(X):def adder(y):return X y return adder c=addx(8)type(c)type function c . _ _ name _ _ adder c(10)18结合这个简单的代码和定义解释闭包:如果是在内部函数中:adder(y)是内部函数,引用了外部作用域(而不是全局作用域)中的变量:X是被引用的变量,X在外部作用域addx中但不在全局作用域中,那么这个内部函数加法器就是闭包。

  稍微详细一点的解释是,闭包=功能块定义一个功能时的环境。加法器是功能块,X是环境。当然,这个环境可以有很多,不止一个简单的x。

  二,使用闭包注意事项中的1,闭包是deffoo():m=0.deffoo1():m=1.打印m.打印m.foo1().打印m.执行结果中的foo () 010

  2.以下代码是在python中使用闭包时的典型错误代码。

  def foo():A=1 defbar():A=a1 return A return bar这个程序的初衷是在每次调用闭包函数时递增变量A。但是在实际使用中

  c=foo() print c()Traceback(最近一次调用last): File stdin ,第1行,在模块文件 stdin ,第4行,BarUnboundLocalError:在赋值前引用了局部变量 A 这是因为当执行代码c=foo()时,python会导入所有闭包函数体bar()来分析其局部变量,python规则规定赋值语句左侧的所有变量都是局部变量,所以在闭包bar()中,变量A位于赋值符号=的左侧,Python将其视为局部变量接下来执行print c()时,当程序运行到a=a 1时,python会在bar()中的赋值语句右侧找到A的值,因为A之前已经在bar()中被归类为局部变量。如果找不到,就会报错。解决办法很简单。

  def foo():A=[1]def bar():A[0]=A[0]1 return A[0]return bar只需将A设置为容器即可。这个用起来有些不舒服,所以在python3之后,a=a 1之前,用语句nonloacal a就够了,它明确指定A不是闭包的局部变量。

  3.当引入python闭包时,还有一种容易出错的情况经常被提及。我从来不认为这个错误与闭包有很大关系,但它确实是python函数式编程中容易犯的错误。我不妨在这里介绍一下。先看下面的代码。

  For i in range(3): print i在程序中经常出现这样的循环语句。Python的问题是,当循环结束时,循环体中的临时变量I不会被销毁,而是继续存在于执行环境中。python的另一个现象是,python函数在执行时只在函数体中寻找变量值。

  flist=[]for I in range(3):def foo(x):print x I flist。在flist: f (2)中为f追加(foo)也许有人认为这段代码的执行结果应该是2,3,4。但实际结果是4,4,4。这是因为当函数被添加到flist列表时,python还没有给I赋值。只有当它被执行时,我才能发现它的价值是什么。此时,第一个for循环结束后,I的值为2,所以上述代码的执行结果为4,4,4。解决方法也很简单。只需重写函数的定义。对于范围(3)中的I:Def Foo(x,y=i): Print x y Flist。Append (foo)三,作用说了这么多,有人要问了,那这个闭包在实际开发中有什么用呢?闭包主要用于功能开发。这里是闭包的两个主要用途。

  1、闭包执行后,仍然可以保持当前的运行环境。例如,如果您希望某个函数的每次执行结果都基于该函数的上次执行结果。我用一个类似棋盘游戏的例子来说明一下。假设棋盘大小为50*50,左上角是坐标系(0,0)的原点,我需要一个接收两个参数的函数,分别是方向和步长。这个函数控制棋子的移动。棋子移动的新坐标除了方向和步长,当然必须以原坐标为基础,可以使用闭包来保持棋子的原坐标。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 _ xpos[1]=new _ y #注意!这里不能写成pos=[new_x,new_y]因为上面已经说过return pos return player player=create()#创建一个棋子玩家,起点是原点打印玩家([1,0],10) #向X轴打印玩家正向移动10步([0,1],20) #向y轴打印玩家正向移动20步([-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 )以上两种使用场景也可以用面向对象轻松实现。但是,在使用Python进行函数式编程时,闭包对于持久化数据和根据配置产生不同的函数非常有帮助。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: