zoukankan      html  css  js  c++  java
  • 闭包(python)

    1.闭包的理解

    我们可以将闭包理解为一种特殊的函数,这种函数由两个函数的嵌套组成,且称之为外函数和内函数,外函数返回值是内函数的引用,此时就构成了闭包。

    2. 闭包的格式

    下面用伪代码进行闭包格式的描述

    def 外层函数(参数):
        def 内层函数():
            print("内层函数执行", 参数)
    
        return 内层函数
    
    
    内层函数的引用 = 外层函数("传入参数")
    内层函数的引用()

    外层函数中的参数,不一定要有,据情况而定,但是一般情况下都会有并在内函数中使用到

    案例

    def func(a, b):
        def line(x):
            return a * x - b
    
        return line
    
    
    line = func(2, 3)
    print(line(5))

    结果得到 7
    在这个案例中,外函数func有接收参数 a=2,b=3,内函数line接收参数x=5,在内函数体中计算了a*x-b 即 2×5-3的值作为返回值,外函数返回内函数的引用,这里的引用指的是内函数line在内存中的起始地址,最终调用内函数line()得到返回值7

    3.内函数中修改外函数的值

    一般在函数结束时,会释放临时变量,但在闭包中,由于外函数的临时变量在内函数中用到,此时外函数会把临时变量与内函数绑定到一起,这样虽然外函数结束了,但调用内函数时依旧能够使用临时变量,即闭包外层的参数可以在内存中进行保留
    如果想要在内函数中修改外函数的值,需要使用 nonlocal  关键字声明变量

    def func(a, b):
        def line(x):
            nonlocal a
            a = 3
            return a * x - b
    
        return line
    
    
    line = func(2, 3)
    print(line(5))

    此时运行结果为:12

    python面试题:

    Python面试题:以下代码将输出什么?

    def testFun(): 
        temp = [lambda x : i*x for i in range(4)] 
        return temp 
    for everyLambda in testFun(): 
        print (everyLambda(2)) 

    脑中默默一想,这还用说么,肯定是:

    0,2,4,6

    然鹅正确答案:

    6,6,6,6

    原因:

    Python 的闭包的后期绑定导致的 late binding,这意味着在闭包中的变量是在内部函数被调用的时候被查找。所以结果是,当任何 testFun() 返回的函数被调用,在那时,i 的值是在它被调用时的周围作用域中查找,到那时,无论哪个返回的函数被调用,for 循环都已经完成了,i ***的值是 3,因此,每个返回的函数 testFun 的值都是 3。因此一个等于 2 的值被传递进以上代码,它们将返回一个值 6 (比如: 3 x 2)

    怎么解决呢??

    1:创建一个闭包,通过使用默认参数立即绑定它的参数

    def testFun(): 
        temp = [lambda x ,i=i: i*x for i in range(4)] 
        return temp 
    for everyLambda in testFun(): 
        print (everyLambda(2)) 

    2:使用functools.partial 函数,把函数的某些参数(不管有没有默认值)给固定住(也就是相当于设置默认值)

    from functools import partial  
    from operator import mul  
    def testFun(): 
        return [partial(mul,i) for i in range(4)] 
    for everyLambda in testFun(): 
        print (everyLambda(2)) 

    3:优雅的写法,直接用生成器

    def testFun(): 
         return (lambda x ,i=i: i*x for i in range(4)) 
         
    for everyLambda in testFun(): 
        print (everyLambda(2)) 

    4:利用yield的惰性求值的思想

    def testFun(): 
        for i in range(4): 
            yield lambda x : i*x 
    for everyLambda in testFun(): 
        print (everyLambda(2)) 
  • 相关阅读:
    zbb20180929 dubbo+zookeeper
    zbb20180929 Linux高可用之Keepalived
    zbb20180929 zk Zookeeper的功能以及工作原理
    zbb20180927 Union与Union All的区别
    zbb20180927 MySQL MyISAM InnoDB区别
    zbb20180921 spring事物的七种事物传播属性行为及五种隔离级别
    zbb20180921 java,md5,MD5加密+加盐
    zbb20180921 java,js,javascript 前端加密后端解密Base64通用加密处理
    zbb20180921 springboot 全局异常处理 404 500
    zbb20180919 db,mysql MySQL慢查询
  • 原文地址:https://www.cnblogs.com/zknublx/p/11968431.html
Copyright © 2011-2022 走看看