#我们前面了解了函数可以有返回值,除了返回值,函数中是否可以返回函数呢?
#例如,定义如下函数并执行:
1 # /usr/bin/python3 2 #!-*-conding:UTF-8 -*- 3 #返回函数 4 5 def calc_sum(*args): 6 ax=0 7 for n in args: 8 ax=ax+n 9 return ax
#这里定义了一个可选参数的求和函数,该函数允许传入多个参数,最后返回求得的和。如果不需要立刻求和,而是在后面的代码中根据需要在计算,怎么操作呢?例如,函数定义如下:
1 def sum_late(*args): 2 def calc_sum(): 3 ax=0 4 for n in args: 5 ax=ax+n 6 return ax 7 return calc_sum
#可以看到,此处返回了一个我们之前没有看过的类型的值,是返回了一个函数吗?是的,此处确实返回了一个函数。对于此处定义的函数,我们返回求和的结果,而是返回了一个求和函数。
#操作执行函数:
1 print('调用sum_late的结果:',sum_late(1,2,3,4)) 2 calc_sum=sum_late(1,2,3,4) 3 print('调用calc_sum的结果:',calc_sum())
#得到函数的执行结果如下:
1 调用sum_late的结果: <function sum_late.<locals>.calc_sum at 0x03141F60> 2 调用calc_sum的结果: 10
#由执行结果看到,调用定义的函数时没有直接返回求和结果,而是返回了一串字符(这个字符其实就是函数)。当执行返回的函数时,才真正计算求和的结果。
#在这个例子中,在函数sum_late中又定义了calc_sum,并且内部函数calc_sum可以引用外部函数sum_late的参数和局部变量。当sum_late返回calc_sum时,相关参数和变量都保存在返回的函数中,称为闭包(closure)。这种程序结构威力极大。
#有一点需要注意,当调用sum_late函数时,每次调用都会返回一个新的函数,即使传入相同的参数也是如此,例如:
1 f1=sum_late(1,2,3) 2 f2=sum_late(1,2,3) 3 print('f1==f2的结果为:',f1==f2)
#执行结果如下:
1 ==================== RESTART: C:/Users/L/Desktop/返回函数.py ==================== 2 f1==f2的结果为: False
#由执行结果看到,返回的函数f1和f2不同。
#我们在此处提到了闭包(closure),什么是闭包呢?
#闭包的定义:如果在一个内部函数里对外部函数(不是在全局作用域)的变量进行引用,内部函数就被认为是闭包。
#在上面的示例中,返回的函数在定义内部引用了局部变量args,当函数返回了一个函数后,内部的局部变量会被新函数引用。
#例如,我们定义一个函数:
1 # /usr/bin/python3 2 #!-*-conding:UTF-8 -*- 3 #返回函数 4 5 def count(): 6 fs=[] 7 for i in range(1,4): 8 def f(): 9 return i*i 10 fs.append(f) 11 return fs 12 f1,f2,f3=count()
#该示例中,每次循环都会创建一个新函数,最后把创建的3个函数都返回了。执行该函数得到的结果是怎样的呢?调用f1(),f2(),f3()的结果是1,4,9吗?
#我们执行如下函数:
1 # /usr/bin/python3 2 #!-*-conding:UTF-8 -*- 3 #返回函数 4 5 def count(): 6 fs=[] 7 for i in range(1,4): 8 def f(): 9 return i*i 10 fs.append(f) 11 return fs 12 f1,f2,f3=count() 13 print('f1的结果是:',f1()) 14 print('f2的结果是:',f2()) 15 print('f3的结果是:',f3())
#执行结果如下:
1 f1的结果是: 9 2 f2的结果是: 9 3 f3的结果是: 9
#由执行结果看到,3个函数返回的结果都是9,为什么全是9?
#原因在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,他们所引用的变量i已经变成了3,因此最终结果为9.
#返回闭包时,返回函数不要引用任何循环变量或后续会发送变化的变量,否则很容易出现很多意想不到的问题。
#如果一定要引用循环变量怎么办?
#我们定义如下函数并执行:
1 # /usr/bin/python3 2 #!-*-conding:UTF-8 -*- 3 #返回函数 4 5 def count(): 6 def f(j): 7 def g(): 8 return j*j 9 return g 10 fs=[] 11 for i in range(1,4): 12 fs.append(f(i)) #f(i)立刻被执行,因此i的当前值被传入f() 13 return fs 14 15 f1,f2,f3=count() 16 print('f1的结果是:',f1()) 17 print('f2的结果是:',f2()) 18 print('f3的结果是:',f3())
#函数执行结果如下:
1 ==================== RESTART: C:UsersLDesktop返回函数.py ==================== 2 f1的结果是: 1 3 f2的结果是: 4 4 f3的结果是: 9
#由执行结果看到,这次输出结果和我们预期的一致。