返回函数
正常的函数如下所示:
1 2 3 4 5 | def calc_sum( * args): ax = 0 for n in args: ax = ax + n return ax |
但如果函数返回值是一个函数,示例如下:
1 2 3 4 5 6 7 | def lazy_sum( * args): def sum (): ax = 0 for n in args: ax = ax + n return ax return sum |
可以看出被返回的函数不带参数,但是它可以引用外部函数如lazy_sum的参数,返回函数名,该函数不立即执行,而是等调用时,使用函数名+()再执行,同样的参数调用返回的函数都是一个新的函数。
调用示例如下:
1 2 3 | >>> f = lazy_sum( 1 , 3 , 5 , 7 , 9 ) >>> f <function lazy_sum.< locals >. sum at 0x101c6ed90 > |
可以看出直接调用lazy_sum(1,3,5,7,9)只会返回求和函数sum,但是返回的函数中又包含了调用时的参数、变量,如1,3,5,7,9,因此使用f()调用时得到25的结果,这种结构称为闭包。对于内部函数而言,引用了外层函数的变量,这种就属于闭包。
1 2 | >>> f() 25 |
其实也可以有办法立即执行,因为return返回了f2(),而不是f2,如下例:
def f1(x):
k=200
def f2():
nonlocal x,k
x*=x
k*=k
print('k'+str(k))#输出40000
print('x'+str(x))#输出10000
f2()
print('k'+str(k))#输出40000
print('x'+str(x))#输出10000
f1(100)
上例还展示了一种情况,内部函数试图改变闭包函数的变量值,但是这种做法是不被允许的,会报错,但是上例中使用了nonlocal关键字,定义了与闭包函数的变量同名的两个变量(x,k均为闭包变量),因此在内部函数作用域内可以对这两个值进行改变,在闭包作用域中,这两个值也发生了改变。
输出如下:
1 2 3 | k200 x100 10000 40000 |
返回函数不仅可以引用外部函数的参数,而且还可以引用外部函数内部定义的局部变量,因此如果返回函数中引用的变量发生变化,会导致出问题,如下例所示:
1 2 3 4 5 6 7 8 9 | def count(): fs = [] for i in range ( 1 , 4 ): def f(): return i * i fs.append(f) return fs f1, f2, f3 = count() |
该例返回了一个函数列表,含有三个函数,调用时因为返回的函数并没有立即执行,而是等到调用了f()才执行,所以实际结果是
1 2 3 4 5 6 | >>> f1() 9 >>> f2() 9 >>> f3() 9 |
就是因为等三个函数都返回时,闭包变量i变成了3,所以最终结果都是9,因此返回函数不能引用任何后续会发生变化的变量。
如果一定要引用循环变量,那么需要再创建一个函数A,循环变量放在该函数A的外围,用循环变量作为该函数A的参数,而该函数A内部返回函数B,引用函数A的参数,此时因为外部循环得到的值是通过参数输入到函数A中,该参数已经固定,不会变化。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步