Python闭包概念的理解

概念

一个函数定义中引用了函数外定义的变量,并且该函数可以在其定义环境外被执行。这样的一个函数我们称为闭包

示例

def outer_func():
    loc_list = []
    def inner_func(name):
        loc_list.append(len(loc_list) + 1)
        print ('%s loc_list = %s' %(name, loc_list))
    return inner_func

clo_func_0 = outer_func()
clo_func_0('clo_func_0')
clo_func_0('clo_func_0')
clo_func_0('clo_func_0')
clo_func_1 = outer_func()
clo_func_1('clo_func_1')
clo_func_0('clo_func_0')
clo_func_1('clo_func_1')

输出结果
clo_func_0 loc_list = [1]
clo_func_0 loc_list = [1, 2]
clo_func_0 loc_list = [1, 2, 3]
clo_func_1 loc_list = [1]
clo_func_0 loc_list = [1, 2, 3, 4]
clo_func_1 loc_list = [1, 2]

对闭包中自由变量的认识如下:

  • 闭包中引用的自由变量只和具体的闭包有关联,闭包的每个实例引用的自由变量互补干扰
  • 一个闭包实例对其自由变量的修改会被传递到下一次该闭包实例的调用

闭包陷阱

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

9
9
9
这个例子中,my_func返回的并不是一个闭包函数,而是一个包含三个闭包函数的一个list。这个例子中比较特殊的地方就是返回的所有闭包函数均引用父函数中定义的同一个自由变量
全部都是9!原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。
返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量
如果必须引用循环变量,如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:

def count():
    def f(j):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1, 4):
        fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
    return fs

应用

利用闭包返回一个计数器函数,每次调用它返回递增整数

def createCounter():
    s[0] = 0
    def counter():
        s[0] = s[0]+1
        return s[0]
    return counter
counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA())
counterB = createCounter()
print(counterB(),counterB(),counterB())

1 2 3 4 5
1 2 3
小结
闭包中引用变量,而不是定义名称一样的变量,即应该是:
s= [0]
def counter():
s[0] = s[0]+1
return s[0]
而不是
s = 0
def counter():
s = s+1
return s
return counter

你可能感兴趣的:(Python闭包概念的理解)