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

本文聚焦Python中匿名函数在列表生成式应用时产生的闭包函数延迟绑定问题。通过示例展示结果与预期不符,将匿名函数转为普通函数便于理解。介绍了用非匿名函数设置形参绑定的解决方法,还解释了闭包函数延迟绑定的特性。

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

先看下面这个函数:

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]

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

给你骨质唱疏松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值