为什么我可以在列表理解中使用 for 循环但不能使用 while 循环

Why can I use for-loops but no while-loops in list-comprehension

我想改进我的 python,所以我决定实现一些数学函数。 我按如下方式实现了整数分解:

def integer_factorization(x):
   if isprime(x):
       return [x]
   factors = []
   for i in sieve_eratosthenes(x):
       while x % i == 0:
           int_fact.append(i)
           x /= i
   return factors

我想return列表中x的所有因素。

现在我想知道我是否可以用列表理解来做到这一点,因为我 return 在任何情况下都是一个列表,它是否增加了函数的可读性(使用这种语法糖就是我的意思当我说我想提高我的 python) 时。

我注意到不可能(或者我只是不知道如何)在列表理解中使用 while 循环,就像在其中使用 for 循环一样。

例如:

#filling l with items of lst with a for loop
def foo1(lst):
   l = []
   for i in list:
      l.append(i)
   return l

#filling l with items of lst with a while loop
def foo2(lst):
   l = []
   i = 0
   while i < len(lst):
      l.append(lst[i])
   return l

foo1()可以“转化”成

def foo1(list):
   return [x for x in list]

但是是否可以像我对 foo1()foo2() 一样使用此列表理解?

如果是,我如何将 integer_factorization() 重写为:

def integer_factorization(x):
   return [x if isprime(x) else for i in sieve_eratosthenes(x) #while x%i==0 ...]

如果这不可能,为什么会这样? for 循环与不能用于列表推导的 while 循环有何不同?

有几件事可以帮助您理解。首先,您的 while 循环示例实际上是一个无限循环。

#filling l with items of lst with a while loop
def foo2(lst):
    l = []
    i = 0
    while i < len(lst):
        l.append(lst[i])
    return l

由于 i 永远不会改变,您的代码将永远添加 lst[0]l

#filling l with items of lst with a while loop
def foo2(lst):
    l = []
    i = 0
    while i < len(lst):
        l.append(lst[i])
        i += 1
    return l

现在您的 while 循环将正确地遍历列表。现在让我们检查 i 的 while 循环中发生了什么。它从 0 开始,递增 1 直到它不再小于 len(lst)。另一种写法是使用 for 循环 (for i in range(0, len(lst), 1):)。在此语法中,i 从 0 开始,当它大于或等于 len(lst) 并递增 1 时退出循环。

#filling l with items of lst with a while loop
def foo2(lst):
    l = []
    for i in range(0, len(lst), 1):
        l.append(lst[i])
    return l

现在可以将其重写为列表理解:

#filling l with items of lst with a while loop
def foo2(lst):
    return [lst[i] for i in range(0, len(lst), 1)]

for 循环和 while 循环可以完成相同的任务,但重要的是要考虑哪种类型的循环更适合该任务。 For 循环非常适合我们知道需要多少次迭代的任务,而 while 循环非常适合我们不知道 运行 循环多少次的任务。对于您的 foo2 函数,很明显我们想要遍历列表中的每个项目,因此 for 循环是最合适的。然后我们能够将其转换为列表推导式 (a) 因为语言的语法允许这样做,并且 (b) 因为列表推导式也是一种结构,最适合在迭代次数明确时使用,例如 1-to -1 关系。对于 integer_factorization(x) 函数,使用 for 循环和 while 循环似乎是合适的。您使用 for 循环遍历 sieve_eratosthenes(x) 返回的有限数字列表,然后使用 while 循环将数字添加到列表 ~while~ 某个条件为真.