Python: 闭包

作者: Ljian1992 | 来源:发表于2015-09-06 00:56 被阅读271次
    闭包的概念

    关于什么是闭包,下面是百度百科的解释

    闭包是可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)

    在Python当中,当函数A返回函数B时, A中的参数和变量都保持在返回函数B中(通过引用计数实现),函数B就是一个闭包,函数A的参数也称为自由变量。

    闭包的一些特性

    惰性求值

    >>> def ret_func(a):
    ...     def func():
    ...         return a
    ...     return func
    ...
    >>> func1 = ret_func(2)
    >>>
    >>> func1()
    2
    

    可以看到,只有在函数调用的时候,才执行函数func1,这就是惰性求值。这个在Django当中的数据查询时的惰性查询就是通过闭包的方式实现的。
    每一次调用都返回一个新的函数

    >>> def ret_func(a):
    ...     def func():
    ...         return a
    ...     return func
    ...
    >>> func1 = ret_func(2)
    >>> func2 = ret_func(2)
    >>>
    >>> func1 != func2
    True
    

    很明显func1 != func2,这也印证每一次调用返回的都是一个新的函数

    闭包要注意的问题

    不要在闭包当中引用任何会发生改变的变量

    在上面的代码当中,函数ret_func_list返回一个list里面保存了3个函数变量,这4个函数都共同的引用了循环变量i, 也就是说它们共享着同一个变量i,i是会改变的,当函数调用时,循环变量i已经是等于2了,因此3个函数返回的都是4。如果,需要在闭包使用循环变量的值的话,把循环变量作为闭包的默认参数或者是通过偏函数来实现。实现的原理也很简单,就是把当把循环变量当参数传入函数时,会申请新的内存。示例代码如下

    >>> def ret_func2():
    ...     arr = []
    ...     for i in range(4):
    ...         arr.append(lambda i=i: i*i)
    ...     return arr
    ...
    >>> results = ret_func2()
    >>> func1 = results[0]
    >>> func2 = results[1]
    >>> func3 = results[2]
    >>>
    >>> func1()
    0
    >>> func2()
    1
    >>> func3()
    4
    

    相关文章

      网友评论

      • Ljian1992:看到两年前写的文章,尴尬到不行。从作用域的角度去理解,一切都是如此简单,简单点来比如就是和类差不多。
        我叫好东西:@Ljian1992 。。。
        yunlux:...

      本文标题:Python: 闭包

      本文链接:https://www.haomeiwen.com/subject/ugqrcttx.html