https://www.cnblogs.com/wlgaojin/p/12292356.html一. 一切皆对象函数式编程并没有标准定义,如果代码非常繁琐则考虑使用。 学习闭包的概念,不是python独有的。 其他大多数语言中的函数只是一段可执行的代码,并不是对象。 python中的函数是对象,一切皆对象。可以把函数赋值给变量: a = 1 a = '2' a = def 甚至可以把函数当作另外一个函数的参数传递或者当成返回值返回,而C#中要封装成委托。 二.什么是闭包:闭包=函数+函数定义时的环境变量我们尝试从概念上去理解一下闭包。 在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。闭包可以用来在一个函数与一组“私有”变量之间创建关联关系。在给定函数被多次调用的过程中,这些私有变量能够保持其持久性。—— 维基百科 用比较容易懂的人话说,就是当某个函数被当成对象返回时,夹带了外部变量,就形成了一个闭包。 1. code1 code2 def curve_pre(): def curve(): print('This is a function') pass return curve #函数可以作为结果返回 f = curve_pre() #函数可以赋值 f()#执行函数,不会报错 #This is a function code3 def curve_pre(): a = 25 #局部变量在curve的外部 def curve(x): #接受抛物线的x值 return a * x * x return curve #返回一个函数 f = curve_pre() print(f(2)) #调用curve()函数 #100 code4 code 3 和 code4 对比 def curve_pre(): a = 25 #局部变量在curve的外部 def curve(x): #接受抛物线的x值 return a * x * x return curve #返回一个函数 a = 10 #定义a = 10 f = curve_pre() print(f(2)) #调用curve()函数 #100 #仍然是a = 25的取值,取得是定义时的环境变量,这就是闭包 函数及其外部环境变量所构成的整体叫做闭包 2.环境变量要在函数外部,但不能是全局变量: a = 25 #a定义为了全局变量 def curve_pre(): def curve(x): #接受抛物线的x值 return a * x * x return curve #返回一个函数 a = 10 f = curve_pre() print(f(2)) #调用curve()函数 #40 #a的值被改变了,因为没有形成闭包 查看: def curve_pre(): a = 25 #局部变量在curve的外部 def curve(x): #接受抛物线的x值 return a * x * x return curve #返回一个函数 a = 10 f = curve_pre() print(f.__closure__) print(f.__closure__[0].cell_contents)#取出闭包的环境变量 print(f(2)) #调用curve()函数 #(<cell at 0x0031AAF0: int object at 0x0FF93A80>,) #25 #这里是a的值 #100 三.一个事例看看闭包1.闭包的意义:闭包保存的是一个环境,把函数现场保存起来了。 闭包 = 函数 + 函数定义时的环境变量(不能是全局变量) 2. 闭包的经典误区 从外层向内层分析 def f1(): a = 10 def f2(): a = 20 #对a重新赋值局部变量,不会影响到外部 print(a) print(a) #10 f2() #20 #f1内部调用f2 print(a) #10 f1() #10 #20 #10 验证其是不是一个闭包: 1 def f1(): a = 10 def f2(): a = 20 # print(a) #print(a) f2() #print(a) f = f1() #f1是None类型 print(f.__closure__) #报错
(2)加上返回值,仍然不是闭包函数: def f1(): a = 10 def f2(): a = 20 #a被认为是一个局部变量了,就不认为是个环境变量了 return a return f2 f = f1() print(f.__closure__) #没有__closure__属性 #None (3)去掉f2()中的赋值后是闭包函数: def f1(): a = 10 def f2(): #a = 20 #删除a = 20,此时a被python认为是一个局部变量 return a return f2 f = f1() print(f.__closure__) #(<cell at 0x02F5AAF0: int object at 0x0FF93990>,) 原因:环境变量不能当作一个变量去赋值,而是一定要去引用外部。 四.出个题,用闭包解决!闭包不是必不可少的东西,只是可以使你的代码架构更加合理。 题目: 旅行者,x = 0 为起点,没走一步加1,计算出旅行者当前所处的位置。
关键点:每次调用时需要调用上次的结果 1.先用非闭包解决一下 origin = 0 def go(step): global origin #将origin变成全局变量 new_pos = origin + step origin = new_pos #等号左边的origin被python认识是局部变量 return origin print(go(2)) print(go(3)) print(go(6)) #2 #5 #11 2.再用闭包解决一下 origin = 0 def factory(pos): #工厂模式 def go(step): nonlocal pos #强制声明不是局部变量 new_pos = pos + step pos = new_pos return new_pos return go tourist = factory(origin) print(tourist(2)) print(origin) print(tourist(3)) print(tourist(6)) #2 #0 #5 #11 并没有改变全局变量origin的值
五.小谈函数式编程
闭包的概念
|
|
来自: 文炳春秋 > 《Python资料》