为什么此循环具有“ 2 for i in range”?它有什么作用?

时间:2019-03-12 14:23:39

标签: python

我正在寻找找到数字所有因素的最佳方法。我找到了这段代码,但我听不懂:

import math

def get_factors(n):
    return sum(2 for i in range(1, round(math.sqrt(n)+1)) if not n % i)

2 for i in range完成什么工作?该代码如何计算因子数量?

1 个答案:

答案 0 :(得分:4)

生成器表达式一次发现两个因子,因此每次找到一对因子时,都需要在计数中加两个。

这是使用更清晰语法的相同循环:

def get_factors(n):
    total_factors = 0
    limit = round(math.sqrt(n) + 1)
    for i in range(1, limit):
        if n % i == 0:
            total_factors += 2
    return total_factors

这如何用作生成器表达式?让我们解压缩语法。生成器表达式的一般形式为:

result-expression for variable in iterable-expression { {1}} if

这将返回一个生成器,该生成器将是一个包含 predicate (可以基于 result-expression 的可迭代对象,但是(在这种情况下不是)针对 variable 为真的给定 iterable-expression 中的每个值。

在这种情况下, predicate 是常数result-expression,因此在 { {1}} 是正确的(也就是说,2在布尔上下文中是2,这意味着predicate会平均划分not n % i)。

整个生成器表达式都传递给True,该表达式采用一个可迭代的参数,并使用i运算符将其减小为单个值;在这种情况下,它需要使用所有n并将它们加在一起以总计。


好,为什么有效?那是一个数学问题,而不是编程问题。

slallum在上面的评论中提到了这一点,但是要了解它是如何工作的,请考虑一下一些因素的影响。

让我们选择一个数字,例如12。12有六个因素:1、2、3、4、6、12:

sum

这里有一个明显的对称性:每个因素与另一个因素配对:

+

两个因子系列相互“交叉”的分界线在哪里?这是平方根。 12的平方根大约是3.46,实际上这就是因素分组所围绕的对称线。这是合乎逻辑的,因为平方根意味着什么:作为一个因素,该数仅被计数一次。

优化是,您只需要计算因子的一半(平方根以下的那些),并且知道平方根上方有相应的因子。因此,每次找到一个小于平方根的因数,便要计算两个因数。

正如slallum在评论中指出的那样,这表明此实现是错误的:对于一个完美的平方,它返回的计数将相减一。例如,16有5个因数:1、2、4、8和16,但此实现将说它有6,因为它两次计数4。