python闭包

本文详细介绍了Python中的闭包概念,通过实例展示了闭包如何在函数内部引用外部变量并保持状态。讨论了闭包的陷阱,解释了为何在循环中直接引用变量会导致错误的结果,并提供了正确的闭包实现方式。最后,探讨了闭包在实际编程中的应用,如函数装饰器,强调了正确使用闭包以避免常见问题的重要性。
摘要由CSDN通过智能技术生成

闭包

概念介绍

  • 简单来说就是一个函数定义中引用了函数外定义的变量,并且该函数可以在其定义环境外被执行。这样的一个函数我们称之为闭包。实际上闭包可以看做一种更加广义的函数概念。因为其已经不再是传统意义上定义的函数。

闭包初探

    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')
  • 在python中我们称上面的这个loc_list为闭包函数inner_func的一个自由变量(free variable)。
  • 闭包中的引用的自由变量只和具体的闭包有关联,闭包的每个实例引用的自由变量互不干扰。
  • 一个闭包实例对其自由变量的修改会被传递到下一次该闭包实例的调用。

闭包陷阱

    def my_func(*args):
        fs = []
        for i in xrange(3):
            def func():
                return i * i
            fs.append(func)
        return fs

    fs1, fs2, fs3 = my_func()
    print fs1()
    print fs2()
    print fs3()
  • 上面这段代码可谓是典型的错误使用闭包的例子。程序的结果并不是我们想象的结果0,1,4。实际结果全部是4。
  • 问题的关键就在于在返回闭包列表fs之前for循环的变量的值已经发生改变了,而且这个改变会影响到所有引用它的内部定义的函数。
  • 因为在函数my_func返回前其内部定义的函数并不是闭包函数,只是一个内部定义的函数。当然这个内部函数引用的父函数中定义的变量也不是自由变量,而只是当前block中的一个local variable。

正确的写法

    def my_func(*args):
        fs = []
        for i in xrange(3):
            def func(_i = i):
                return _i * _i
            fs.append(func)
        return fs

    def my_func(*args):
         fs = []
         for i in xrange(3):
             func = lambda _i = i : _i * _i
             fs.append(func)
         return fs
  • 正确的做法便是将父函数的local variable赋值给函数的形参。函数定义时,对形参的不同赋值会保留在当前函数定义中,不会对其他函数有影响。
  • 另外注意一点,如果返回的函数中没有引用父函数中定义的local variable,那么返回的函数不是闭包函数。

闭包的应用

    def func_dec(func):
        def wrapper(*args):
            if len(args) == 2:
                func(*args)
            else:
                print 'Error! Arguments = %s'%list(args)
        return wrapper

    @func_dec
    def add_sum(*args):
        print sum(args)

    # add_sum = func_dec(add_sum)
    args = range(1,3)
    add_sum(*args)

参考

理解Python闭包概念

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值