• python高阶函数——返回函数(闭包)


    首先,来看一个一般意义的求和:

    >>> def cal_sum(*args):
    ...     sum = 0
    ...     for i in args:
    ...             sum = sum + i
    ...     return sum
    ...
    >>> cal_sum(1,2,3,4)
    10

    如果我们这么定义呢:

    >>> def lazy_sum(*args):
    ...     def sum():
    ...             sum = 0
    ...             for i in args:
    ...                     sum = sum + i
    ...             return sum
    ...     return sum
    ...
    >>> l = lazy_sum(1,2,3,4)
    >>> l
    <function lazy_sum.<locals>.sum at 0x00E4A198>

    我们发现,这种定义的函数,返回的并不是一个具体的求和,而是一个函数!来看看怎么调用这个函数:

    >>> l()
    10

    在这个例子中,lazy_sum中又定义了一个函数sum(),这个内部函数可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这就是‘闭包’。

    再来试验一下:

    >>> l1=lazy_sum(1,2,3,4)
    >>> l2=lazy_sum(1,2,3,4)
    >>> l1==l2
    False
    

     我们发现,l1和l2互不影响!这说明lazy_sum每次调用都返回一个新函数,即使传入的参数相同。

    其实,返回的函数在其定义的内部引用了局部变量args,当一个函数返回了一个函数后,其内部的局部变量还能被新函数引用。另外,返回的函数并没有立即被执行,而是直到调用了l()后才执行。通过下面的例子再来加深一下印象

    例子1:

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

    全部都是9,并不是1,4,9.原因在于返回的函数引用了变量i,但它并没有立即执行。等三个函数都返回时,他们所引用的变量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
    ...
    >>> f1,f2,f3 = count()
    >>> f1()
    1
    >>> f2()
    4
    >>> f3()
    9
  • 相关阅读:
    菜单、toast、对话框的使用
    对话框应用反射销毁
    java随机汉字生成
    Android从主界面退出
    Android获取网络状态
    ssh secure shell 乱码问题
    MongDB安装使用
    安装scrapy
    列表查找以及二分查找
    Tuple、list的区别以及dict和set
  • 原文地址:https://www.cnblogs.com/hiwuchong/p/8108229.html
Copyright © 2020-2023  润新知