Scipy Hermite多项式作为Lambda函数存入列表时行为异常的解决问询
解决列表推导式中Lambda捕获变量导致的Hermite多项式函数重复问题
这个问题我太熟悉了!这是Python里经典的闭包变量引用陷阱——你用lambda定义函数时,它并没有在循环的每一步把当时的i值“固定”下来,而是保留了对变量i的引用。等你后续调用这些函数的时候,整个循环已经跑完了,i的值已经变成了4(也就是range(5)的最后一个元素),所以所有lambda都会调用hermite(4)(x),结果自然全是-20.0。
给你三种靠谱的解决方法,从最简单到最通用:
方法1:直接存入hermite(i)返回的函数(最推荐)
其实scipy.special.hermite(n)本身就会返回对应阶数的多项式函数,你完全不需要多此一举用lambda包装!直接把这些函数存入列表就好:
from scipy.special import hermite base_funcs = [hermite(i) for i in range(5)] # 测试一下 [f(1) for f in base_funcs] # 输出:[1.0, 2.0, -2.0, -12.0, -20.0]
这种写法最简洁,也完全避开了变量捕获的问题,是最优解。
方法2:用默认参数绑定当前i值
如果你确实需要用lambda(比如后续要加额外逻辑),可以通过给lambda设置默认参数的方式,把循环时的i值绑定进去:
from scipy.special import hermite base_funcs = [lambda x, i=i: hermite(i)(x) for i in range(5)] [f(1) for f in base_funcs] # 输出:[1.0, 2.0, -2.0, -12.0, -20.0]
这里的i=i是关键:在每次循环迭代时,Python会把当前的i值作为默认参数传入lambda,相当于把值“快照”在了函数定义的时刻,而不是保留对变量的引用。
方法3:用functools.partial固定参数
如果要处理更复杂的参数绑定场景,functools.partial是个更专业的工具,它可以帮你提前固定函数的部分参数:
from scipy.special import hermite from functools import partial base_funcs = [partial(hermite(i)) for i in range(5)] [f(1) for f in base_funcs] # 输出:[1.0, 2.0, -2.0, -12.0, -20.0]
partial(hermite(i))会直接生成一个已经绑定了阶数i的函数,用法和直接调用hermite(i)返回的函数完全一致,代码也很清晰。
随便验证几个结果:
print(base_funcs[0](1)) # 1.0,对应Hermite 0阶多项式在x=1处的值 print(base_funcs[2](1)) # -2.0,对应Hermite 2阶多项式在x=1处的值
完全符合预期。
内容的提问来源于stack exchange,提问作者Vim
相关产品推荐
相关产品推荐

