当前位置: 首页 > 后端技术 > PHP

简单说一下闭包的作用

时间:2023-03-30 05:04:01 PHP

closure一句话,闭包的作用:把方法存到一个变量里。至于闭包的原因或者目的,或者说为什么把方法存到一个变量里,后面再说。闭包的条件为了避免长篇大论地描述一个概念,我们将闭包的条件合理地分为三类:在外函数中定义了一个内函数,内函数使用了外函数的变量,以及外层函数返回内层函数的引用,或者说,外层函数直接调用了内层函数P.S。外函数和内函数是指嵌套函数中的外函数和内函数。语言自然不支持这种闭包条件3分为两类,更多的时候是前一类,后一类(外层函数直接调用内层函数)用的比较多,保证代码的简洁性,以及像这样保持简洁并不一定需要闭包。闭包示例“空谈很便宜,给我看看你的代码。”我总觉得在编程中,太多的人类语言会产生太多的歧义,甚至可能过于抽象,观众无法理解。概念性理解。解决这个问题最好的方法就是看代码。编程语言相对于人类语言的优势之一是它们大大减少了语言的歧义。同时,通过多个代码实例,人脑会很自然地提取出多个实例中的共同点,进而理解抽象的概念。结合闭包的三个条件,我们来看一下闭包的例子:defouter(b):definner(a):#condition1print(a+b)#condition2returninner#condition3#callo=outer(1)o(2)Python的代码非常简单。一般情况下,函数结束后,函数中的变量应该被销毁,但是这个闭包是个特例——o和o2中的1和20被保留了下来。o和o2似乎有种似曾相识的感觉,它们就像是两个对象——这两个“对象”来自同一个“类”,而这两个“对象实例”的区别在于加数不同,即1和分别是20个(当然这两个变量的引用地址也不一样)。现在,我们把代码示例中的第三个条件,即“外层函数返回一个内层函数的引用”改成“外层函数直接调用内层函数”:defouter(a,b):definner(a):#Condition1print(a+b)#Condition2inner(b)#Condition3#Callo=outer(100,1)此时整个闭包函数像普通函数一样被调用,传入两个参数,打印也按预期到达。只能说,当外层函数中的逻辑过于复杂时,内层可以将复杂的代码“模块化”,重新调用,可以增加简单性。在这种情况下,通常只调用一次内层函数,而且只在这里调用,所以这里更容易管理。接下来,让我们欣赏一下其他语言中类似的闭包:funcouter(iint)func()int{returnfunc()int{//condition1(anonymous)+condition3i++//condition2returni}}//Callo:=outer(1)o()Golang示例闭包与Python示例有很大不同,因为这里将inner函数替换为匿名函数,看起来更酷。而下面的php和Python几乎一样。函数外部($str1){$outerStr=$str1;$inner=function($str2){//条件1echo$str2.$外链;//条件2};返回$内部;//条件3}//调用$o=outer("hahaha");$o("嗯嗯");闭包的原因新手看了上面的例子,应该对闭包的概念有了一定的了解,甚至有了一些想法。回到最初的问题,关闭的原因。如果说“将方法存储在变量中”是闭包的目的,那么下一个问题就很明显了:为什么要将方法存储在变量中?直接调用方法(函数)不好吗?闭包保存了函数的状态信息。我们还是以开头的例子为例:defouter(b):definner(a):print(a+b)returninnero=outer(1)o(2)#3o(100)#101o2=outer(20)o2(100)#变量120o对应的闭包保存了b=1的信息,无论调用o(2)还是o(100),b=1的信息都会存在,后面的参数参与一起操作。同理,变量o2对应的闭包存储了信息b=20。由于函数退出后并没有被销毁,所以这个闭包的信息也没有被销毁,所以这个信息可以在后面使用。语法糖为了让代码简洁易懂,我们经常会使用甚至创建一些语法糖。在Python中,有一个非常好看的装饰器例子。举个用不好的例子,面向切面的登录实现:#先实现一个类似装饰器的函数defdecorator(func):definner():print'beforefunction'func()#functionprint'afterfunction'returninner#实现一个假装登录的登录函数deflogin():print'loginfunctioncomplete.'#用装饰器“包装”登录函数login=decorator(login)login()整个过程类似于AOP,场景也很常见,比如统计函数的运行时间,添加日志,统一过滤等等。更重要的是,在特定场景下使用闭包创建语法糖来简化代码。参考这个例子,可以代替switch(不过这里这么简单的加减运算很弱智,必须有一定的复杂度才能显得优越):defoperator(o):defplus(x,y):print(x+y)defminus(x,y):print(x-y)ifo=='+':returnplusifo=='-':returnminusdeff(x,o,y):运算符(o)(x,y)Lambda,著名的函数式编程,可以参考这个链接。总结闭包可以将方法存储在变量中,实现一些美好的东西。它就像调味品,不是不可或缺,但可以锦上添花。让我们先做这个。如有错误请指出,炸鱼多加注意。