能否通过链式生成器表达式,让下游条件避免上游未检查元素的求值?
解决生成器表达式中不必要的求值问题
这个问题确实说到了生成器表达式的一个常见局限:默认情况下,生成器里的整个元组会被完整求值后才yield出来,哪怕后续的筛选逻辑根本用不到其中的某些元素。就像你遇到的情况,不管i是不是10的倍数,i**2都会提前算出来,白白浪费了计算资源。
不用大改第一个生成器的话,最简单的办法是把需要延迟计算的部分包装成一个懒加载的可调用对象,比如lambda函数,这样只有当条件满足、真正需要这个值的时候才去计算它。
具体实现步骤:
- 修改第一个生成器,把
i**2替换成捕获当前i值的lambda:
items = ((i, lambda x=i: x**2) for i in range(0, 100))
这里用x=i是为了避免lambda的延迟绑定问题——如果直接写lambda: i**2,所有lambda都会引用最后一个i的值,而不是生成时的i。
- 在第二个生成器里,只有当条件满足时才调用这个lambda来获取平方值:
tens = ((i, j()) for i, j in items if i % 10 == 0)
这样一来,当i不是10的倍数时,j这个lambda根本不会被执行,x**2也就不会被计算,完美实现了按需求值的效果。
为什么这个方法好用?
- 对原生成器的改动极小,只是把求值逻辑包装了一层,不需要重构整个生成器的结构;
- 逻辑清晰,一眼就能看出来哪些是懒加载的部分;
- 没有引入额外的复杂依赖,只用了Python内置的lambda表达式。
如果觉得lambda不够直观,也可以用一个简单的函数代替,比如:
def square(x): return x**2 items = ((i, square) for i in range(0, 100)) tens = ((i, j(i)) for i, j in items if i % 10 == 0)
不过这种写法每次都要传入i,不如lambda捕获值的方式简洁。
内容的提问来源于stack exchange,提问作者SpatialHorizon
相关产品推荐
相关产品推荐

