2

我一直在用 python 列表推导弄乱一点,并创建了这个单行来计算作为两个三位数乘积的最大偶数:

max([ i*j for i in range(100,1000) for i in range(100,1000) if i*j%2== 0 ]) 

问题如下:有没有办法避免重新计算 i*j 的值,比如为其分配一个临时名称并使用它?

让我感到震惊的是我计算了i*j两次的值,如果我想要一个 if 函数,我还需要一个。有什么办法可以解决吗?

4

3 回答 3

3

如果i*j价格昂贵,请使用生成器功能:

def values():
    for i in range(100, 1000):
        for j in range(100, 1000):
            ij = i * j
            if ij % 2 == 0:
                yield ij

max(values())

抵制在这里嵌套生成器表达式的诱惑;是的,它可以做到,但只会使您的代码无法破译。

于 2013-03-20T12:32:34.683 回答
0

我不确定解释器如何处理您的代码。

但你可以使用:

max((u for u in (i*j for i in range(100,1000) for j in range(100,1000)) if u%2== 0))

在这种情况下,我认为最好使用生成器 () 而不是使用列表 [],因为您不需要所有数据,只需要最大数据。

于 2013-03-20T12:37:53.520 回答
0

一般来说,Python 的哲学是这样说的:如果你想重用一些中间结果,那就给它一个名字。习惯 _上,用于建议一个临时名称。此外,如果列表推导式或生成器表达式跨越两行或多行,最好还是用显式的 for 循环重写它。

也就是说,人们可能(错误地)使用 Python 的函数功能来编写没有任何中间名称的代码。几乎,就是:因为我们不能使用functools.partial固定非最左边和非关键字参数,我们必须自己构造一个mod2函数而不是使用partial.

from itertools import iterfalse, product, starmap
from operator import mod, mul
mod2 = lambda x: mod(x, 2) # this would be nicer with functools.partial
max(filterfalse(mod2, starmap(mul, product(range(100, 1000), repeat=2))))

然而,虽然我相信上面的代码回答了你的问题,但我认为这个解决方案在直觉上并不容易理解——只需给你的中间结果一个名字。

于 2013-09-02T11:00:25.140 回答