• 匿名函数在列表生成式中的应用产生的闭包函数延迟绑定问题


    匿名函数在列表生成式 (推导式) 中的应用产生的闭包函数延迟绑定问题

    先看下面这个函数:

    def num():
        return [lambda x: x * i for i in range(4)]
    
    print([func(2) for func in num()])
    

    再不运行结果的情况下心算下它的结果......是不是算到 [0,2,4,6] ?

    于是在pycharm里面运行了一下 : [6,6,6,6], 百思不得其解, 我们先来把匿名函数变成普通函数, 这样好理解一点 :

    def num():
        sub=[]
        for i in range(4):
            def bar(x):
                return i*x
            sub.append(bar)
        return sub
    
    print([func(2) for func in num()])
    

    我们可以看到它是一个闭包函数的结构, 看 num( ) 返回的列表里面放的应该是四个 bar 函数的内存地址 : [bar, bar, bar, bar] , 并没有去调用 bar 函数

    def num():
        # 返回值是一个列表生成式, 里面存放了四个而函数对象
        return [lambda x: x * i for i in range(4)]
    
    for i in num():
        print(i)
    '''
    <function num.<locals>.<listcomp>.<lambda> at 0x000002AA99D2CE58>
    <function num.<locals>.<listcomp>.<lambda> at 0x000002AA99D2CDC8>
    <function num.<locals>.<listcomp>.<lambda> at 0x000002AA99EE4708>
    <function num.<locals>.<listcomp>.<lambda> at 0x000002AA99EE4D38>
    '''
    

    当执行print([func(2) for func in num()]) 的时候, 这才触发了每个 bar 函数的执行, 此时的 for 循环已经结束了, 最终的 i = 3, 所以每次的结果都是 2*3=6

    非匿名函数解决方法

    在内层函数 bar 形参位置设置一个接收 i 的参数, 让其绑定

    def num():
        sub=[]
        for i in range(4):
            def bar(x,n=i):
                return n*x
            sub.append(bar)
        return sub
    
    print([func(2) for func in num()])  # [0, 2, 4, 6]
    

    闭包函数延迟绑定问题解释

    在函数嵌套的时候, 如果一个循环返回的是一个函数对象, 该函数对象出现引用的时候并不会立即引用循环的值, 而是在运行(调用)嵌套函数的时候才会去查找该引用的值, 这个特性就是闭包函数的延迟绑定

  • 相关阅读:
    读spring Micro-Service tats收获
    读spring Micro-Service tats收获
    读spring Micro-Service tats收获
    读Software Entity Architektur收获
    读Software Entity Architektur收获
    读Software Entity Architektur收获
    mvc案例
    11.16
    11.15
    11.13
  • 原文地址:https://www.cnblogs.com/songhaixing/p/14273991.html
Copyright © 2020-2023  润新知