python闭包

先看一个闭包的用法:

# -*- coding:utf-8 -*-
def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()
print count()   #实质就是 fs 列表的内容
print f1()
print f2()
print f3()

结果是:

9

9

9

这说明返回的函数并没有立刻执行,而是直到调用了f()才执行,而此时它们所引用的变量i已经变成了3,因此最终结果为9。

试着改进:

# -*- coding:utf-8 -*-

def count():
    fs = []
    for i in range(1, 4):
        def f(i):
             return i*i
        fs.append(f(i))
    return fs

f1, f2, f3 = count()

print f1,f2,f3

#测试一下python的赋值机制
print '\n'

a,b,c=[1,2,3]
print a
print b
print c
#结论:分别赋值,依次对应


上面的代码其实和下面的是没有区别的,

要特别注意函数有括号时和没有括号时的区别(把第一段代码和下面的代码比较)

# -*- coding:utf-8 -*-

def count():
    fs = []
    for i in range(1, 4):
        def f():
              return i*i
        fs.append(f())
    return fs

f1, f2, f3 = count()

print count
print count()

print f1,f2,f3

虽然能得到我们想要的结果,但上面一段代码并没有用到闭包,和 fs.append(i*i)  没有区别。

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:

正确的闭包用法应该如下:

def count():
    fs = []
    for i in range(1, 4):  
         def f(j):        #1
             def g():     #2
                return j*j
             return g     # g函数实质上是f函数的一个闭包
         fs.append(f(i))  #i会作为参数,先传递给#1,作为 j 传递给g函数#2,对于每一个i来说,都被g函数锁定了.fs =【f(1),f(2),f(3)】
    return fs


f1,f2,f3=count()
print f1
print f1()
print f2()
print f3()

特别值得注意的是,g函数实质上是f函数的一个闭包。每次调用f()时,才具体计算g函数,而print f1时,实际上得到的是函数g——内层函数的返回值

闭包就是把函数作为返回值,具体实现就是函数的嵌套,在这里是 f 函数套 g 函数
内层函数调用外层函数的参数(j)和局部变量,并实现具体的运算,返回值作为内层函数的返回值
外层函数 f 的【返回值】就是内层函数 g ,而非具体的运算结果

要想用外层函数得到具体的返回值,就得调用外层函数

如 f1(),f2(),f3()


函数作为返回值的例子:

# -*- coding:utf-8 -*-


#所谓的函数作为返回值,具体实现就是函数的嵌套,#1套#2
#内层函数调用外层函数的参数(args)和局部变量,并实现具体的运算,返回值作为内层函数的返回值 #3
#外层函数的【返回值】就是内层函数 #4,而非具体的运算结果 #3,可参考#5。
#要想用外层函数得到具体的返回值,就得调用外层函数 #6
def lazy_sum(*args):   #1
	def sum():         #2
		ax=0
		for i in args:
		    ax = ax + i
		return ax       #3
	return sum          #4
	
	
f=lazy_sum(1,3,5,7)    #让f指向lazy_sum,实际上f即lazy_sum
print f               #5
print f.__name__

print f() 
print lazy_sum(1,3,5,7)  # 等于 print f

#当我们调用lazy_sum时,每次调用都会返回一个不同的函数,即使传入相同的参数
f1=lazy_sum(1,3,5,7)
f2=lazy_sum(1,3,5,7)
print f1==f2             #false


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值