python中闭包必须存在于什么关系的函数中,python构成闭包的条件

  python中闭包必须存在于什么关系的函数中,python构成闭包的条件

  1.定义

  闭包是函数式编程的重要语法结构,函数式编程是一种编程范式(而面向过程编程和面向对象编程也是编程范式)。在面向过程的编程中,我们见过function);在面向对象编程中,我们见过object。函数和对象的根本目的是以逻辑的方式组织代码,提高代码的可重用性。闭包也是一种组织代码的结构,也提高了代码的重用性。

  不同的编程语言有不同的方法来实现闭包。在python中,闭包用形式来表示。如果外部作用域(而不是全局作用域)中的变量在内部函数中被引用,那么内部函数被认为是一个闭包。

  例如:

  外部定义(x):

  内部定义(y):

  返回x y

  返回内部

  一个

  2

  三

  四

  五

  结合这个简单的代码和定义来说明闭包:

  Inner(y)就是这个内部函数,引用外部作用域(但不在全局作用域)的变量:X是被引用的变量,如果X在外部作用域outer但不在全局作用域,那么这个内部函数Inner就是一个闭包。

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

  内部函数在外部函数中定义。内部函数访问外部函数的(参数)变量,并将内部函数作为返回值返回给外部函数。

  a=外部(2)

  打印(函数:,a)

  打印(结果:,a(3))

  一个

  2

  三

  a是上面代码中的一个函数,代码的执行结果是:

  由此,不难看出,A是函数inner而不是outer。这有点绕,但也不难理解,因为return返回的是内部函数。

  print(a.func_name ,a.func_name)

  一个

  输出是:

  调用函数A,结果是传入参数值的相加。

  上面和这句话一样:print(result:,outer(2)(3))

  2.使用闭包时需要注意什么

  2.1闭包不能修改外部函数的局部变量。

  如果innerFunc可以修改x的值,那么x的值会前后变化,但结果是:

  x的值在innerFunc中改变了,但在outerFunc中没有改变。

  我们再举一个例子。

  2.2闭包不能直接访问外部函数的局部变量。

  定义外部():

  x=5

  Def inner():上面一行中的# X是相对于内部函数的函数外部的局部变量(非全局变量)。

  x *=x

  返回x

  返回内部

  外部()()

  一个

  2

  三

  四

  五

  六

  七

  八

  运行时会出现错误:

  解决方案是:

  1.在python3之前,没有直接的解决方法,只能通过容器类型间接解决,因为容器类型不存储在堆栈空间中,可以被内部函数访问。

  定义外部():

  x=[5]

  内部定义():

  x[0] *=x[0]

  返回x[0]

  返回内部

  print(outer()()) #25

  一个

  2

  三

  四

  五

  六

  七

  八

  2.python3由nonlocal关键字解决,该关键字显式指定A不是闭包的局部变量。

  定义外部():

  x=5

  内部定义():

  非局部x #将x声明为非局部变量

  x *=x

  返回x

  返回内部

  print(outer()())

  一个

  2

  三

  四

  五

  六

  七

  八

  九

  2.3python循环不包含域的概念。

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

  对于范围(3)中的I:

  打印I

  一个

  2

  三

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

  flist=[]

  对于范围(3)中的I:

  def foo(x):打印x i

  对于flist中的f:

  女(2)

  一个

  2

  三

  四

  五

  六

  可能有人会觉得这段代码的执行结果应该是2,3,4。但实际结果是4,4,4。loop python中没有域的概念。flist在图像列表中加入func时,并没有保存I的值,只是在执行f(2)时取它。这时候循环已经结束,I的值是2,所以结果都是4。

  解决方法也很简单,重写函数的定义就行了。

  对于范围(3)中的I:

  def foo(x,y=i): print x y

  flist.append

  一个

  2

  三

  四

  3.闭包的功能

  说到这里,有人要问了,这种封闭在实际开发中有什么用?闭包主要用于功能开发。这里是闭包的两个主要用途。

  1.目的:执行闭包后,仍然可以保持当前的运行环境。

  例如,如果您希望某个函数的每次执行结果都基于该函数的上次执行结果。我用一个类似棋盘游戏的例子来说明一下。假设棋盘大小为50*50,左上角是坐标系(0,0)的原点,我需要一个接收两个参数的函数,分别是方向和步长。这个函数控制棋子的移动。棋子移动的新坐标除了方向和步长,当然必须以原坐标为基础,可以使用闭包来保持棋子的原坐标。

  原点=[0,0]

  legal_x=[0,50]

  legal_y=[0,50]

  定义创建(位置=原点):

  定义玩家(方向,步):

  #这里首先要判断参数方向和步长的合法性,比如方向不能走对角线,步长不能为负数等。

  #然后,需要判断新生成的X、Y坐标的合法性。这里主要想介绍一下闭包,就不详细写了。

  new_x=pos[0]方向[0]*步长

  new_y=pos[1]方向[1]*步长

  pos[0]=new_x

  pos[1]=new_y

  #注意!这里不能写成pos=[new_x,new_y],因为参数变量不能修改,pos[]是容器类的解。

  退货位置

  返回播放器

  Player=create() #以原点为起点创建一个棋子玩家。

  Print ([1,0],10) #在X轴正方向移动10步

  Print ([0,1],20) #沿Y轴正方向移动20步

  Print player([-1,0],10) #在X轴的负方向移动10步

  一个

  2

  三

  四

  五

  六

  七

  八

  九

  10

  11

  12

  13

  14

  15

  16

  17

  18

  19

  输出是:

  [10, 0]

  [10, 20]

  [0, 20]

  一个

  2

  三

  目的:闭包可以根据外部作用域的局部变量得到不同的结果。

  这有点像配置函数。我们可以修改外部变量,闭包根据这个变量显示不同的函数。比如有时候我们需要分析一些文件的专用线,先把这些专用线提取出来。

  def make_filter(保留):

  定义过滤器(文件名):

  file=open(文件名)

  lines=file.readlines()

  file.close()

  filter _ doc=[I for I in lines if keep in I]

  返回过滤器_文档

  返回_过滤器

  一个

  2

  三

  四

  五

  六

  七

  八

  如果我们需要获取文件“result.txt”中带有关键字“pass”的行,我们可以像这样使用示例程序。

  filter=make _ filter( pass )filter _ result=filter( result . txt )

  一个

  2

  以上两种使用场景,用面向对象也很容易实现,但是在用Python进行函数式编程时,闭包对于数据持久化和根据配置不同的功能是很有帮助的。

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

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