Python sum(generator):调用外部函数

3

拿出代码:

SUM = sum(x() for x in xs)

我正在编写一些代码,需要在每个x()之前调用另一个函数,以便x()计算出正确的值。这是唯一的方法吗?
for x in xs: x.pre()

SUM = sum(x() for x in xs)

或者

SUM = 0
for x in xs:
    x.pre()
    SUM += x()

将 x.pre 整合到 x 中显然是可行的,但会使真正的代码异常丑陋和难以阅读。我是否有一些不知道的使用生成器表达式的方法,可以实现我想要的效果?
例如:
SUM = sum(x(), x.pre() for x in xs) 

显然,这只是一个无法求和的元组生成器。


另一种特别丑陋的方法是 sum((x.pre(), x())[1] for x in xs)... - tobias_k
2
不使用 sum() 内置函数的显式 for 循环是一个非常好的解决方案。它非常易读,我看不到任何缺点。 - Sven Marnach
1
@Sven:通常我会说它有一个(轻微的)缺点,即它使用了可变变量,但由于所有这些“x”对象都是可变的,因此在阅读此代码时需要考虑状态的推理量微不足道 :-) - Steve Jessop
初始化SUM=0实际上是一个非常复杂的调用,我正在尝试避免这种巨大的语法混乱。 - user2255757
1个回答

1
我建议直接使用你已经提供的for循环。
还有其他方法可以实现你想要的功能。例如,你可以使用自定义函数和functools.reduce来代替sum
def pre_then_add(accumulated, new_one):
    new_one.pre()  # do some stuff so we get the right value
    return accumulated + new_one() # add the value to the accumulated sum

然后只需调用reduce函数即可:

import functools

functools.reduce(pre_then_add, xs, 0)

请注意,这需要提供一个“基础值”,否则函数太简单了。但是,使用自定义函数的reduce不一定是最有效或最优雅的方法。
正如评论中指出的(感谢@SteveJessop),另一种可能性是使用sum
def pre_then_call(x): 
    x.pre(); 
    return x()

sum(pre_then_call(x) for x in xs)

但是我想再重复一遍:我会使用显式循环。这些循环更容易理解你在做什么以及为什么要这样做。


2
同样地,您可以使用 def pre_then_call(x): x.pre(); return x(),然后使用 sum(pre_then_call(x) for x in xs) - Steve Jessop
@SteveJessop我知道我不应该包含这个例子。我只是为了展示这种方法如何更不易读(在我看来),并且只是“外包”了实际完成的工作。至少只要它不是内置的 - 在实际性能原因可以证明这样的“sum”时。 - MSeifert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接