Python3之返回函数
参考:https://www.cnblogs.com/mzc1997/p/7641995.html
Python中函数不仅可以作为参数还可以作为结果返回
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>> def pro1(c,f): ... def pro2(): ... return f(c) ... return pro2 #调用函数pro1函数时,返回的是pro2函数对象 >>> a = pro1( - 3 , abs ) >>> a <function pro1.< locals >.pro2 at 0x7fe07ed4eea0 > #需要对a调用才能得到结果 >>> a() 3 #执行了a()相当于f(c)执行了 abs(-3)返回为3 |
如果在一个内部函数里对外部作用域(但不是全局作用域)的变量进行引用,内部函数称为闭包(closure)
1 2 3 4 5 6 7 8 9 10 | >>> def fun1(n): ... def fun2(x): ... return pow (x,n) ... return fun2 ... >>> pow2 = fun1( 2 ) >>> pow2 <function fun1.< locals >.fun2 at 0x7f8bdfe2e378 > >>> pow2( 9 ) 81 |
函数fun2对fun1的参数n进行了引用,将带参数的fun1给一个新的函数pow2,新的函数再加一个参数x运行,则相当于pow(9,2) 9的二次方
当fun1的生命周期结束时,已经引用的变量n存在fun2中,依然可以调用
在看一个例子count.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | def count(): fs = [] for i in range ( 1 , 4 ): def f(): return i * i #把函数f地址追加至列表fs fs.append(f) #返回为一个包含3个函数f地址的列表 return fs print ( 'count函数返回一个列表,列表分别为函数f地址' ,count()) f1,f2,f3 = count() print (f1, 'f1执行结果是' ,f1()) print (f2, 'f2执行结果是' ,f2()) print (f3, 'f3执行结果是' ,f3()) |
运行结果
1 2 3 4 | count函数返回一个列表,列表分别为函数f地址 [<function count.< locals >.f at 0x7fc5d30cac80 >, <function count.< locals >.f at 0x7fc5d30cad08 >, <function count.< locals >.f at 0x7fc5d30cad90 >] <function count.< locals >.f at 0x7fc5d30cac80 > f1执行结果是 9 <function count.< locals >.f at 0x7fc5d30cad08 > f2执行结果是 9 <function count.< locals >.f at 0x7fc5d30cad90 > f3执行结果是 9 |
结果全是9不是预期的1,4,9
结果全部都是9. 不是预期的1,4,9。
原因是返回函数引用了变量i,下面来解析一下f1,f2,f3=count()这句的执行过程:
当i=1, 执行for循环, 结果返回函数f的函数地址,存在列表fs中的第一个位置上。
当i=2, 由于fs列表中第一个元素所指的函数中的i是count函数的局部变量,i也指向了2;然后执行for循环, 结果返回函数f的函数地址,存在列表fs中的第二个位置上。
当i=3, 同理,在fs列表第一个和第二个元素所指的函数中的i变量指向了3; 然后执行for循环, 结果返回函数f的函数地址,存在列表fs中的第三个位置上。
所以在调用f1()的时候,函数中的i是指向3的:
f1():
return 3*3
同理f2(), f3()结果都为9
闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。即包在里面的函数(本例为f()),不要引用外部函数(本例为count())的任何循环变量
如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:
count_2.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | def count(): fs = [] for i in range ( 1 , 4 ): def f(j): def g(): return j * j return g fs.append(f(i)) #返回为一个包含3个函数f地址的列表 return fs print ( 'count函数返回一个列表,列表分别为函数f地址' ,count()) f1,f2,f3 = count() print (f1, 'f1执行结果是' ,f1()) print (f2, 'f2执行结果是' ,f2()) print (f3, 'f3执行结果是' ,f3()) |
1 2 3 4 | count函数返回一个列表,列表分别为函数f地址 [<function count.< locals >.f.< locals >.g at 0x7ff488311d08 >, <function count.< locals >.f.< locals >.g at 0x7ff488311c80 >, <function count.< locals >.f.< locals >.g at 0x7ff488311d90 >] <function count.< locals >.f.< locals >.g at 0x7ff488311c80 > f1执行结果是 1 <function count.< locals >.f.< locals >.g at 0x7ff488311d08 > f2执行结果是 4 <function count.< locals >.f.< locals >.g at 0x7ff488311d90 > f3执行结果是 9 |
结果就是预期的1,4,9.
当i=1时,f(1)即让j指向1,
当i=2时,f(2)即让j指向2,此时j不是count的局部变量,不会影响到i=1是f(1)中j的指向。即函数f的参数绑定循环变量当前的值, 而不是循环变量本身。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
2018-06-21 Redis主从配置及主从切换
2017-06-21 ELKStack可视化