我试图更好地理解列表推导如何工作。 我有以下函数返回true或false如果一个数字是素数(我在论坛的某处找到但不记得在哪里):
import math
def is_prime(n):
if n % 2 == 0 and n > 2:
return False
for i in range(3, int(math.sqrt(n)) + 1, 2):
if n % i == 0:
return False
return True
如果我跑:
[x for x in range(2, num) if is_prime(x)]
我得到了理想的结果
[2, 3, 5, 7, 11, 13, 17, 19]
在尝试将整个函数转换为列表理解时,我提出了:
[x if not (x%2==0 and x > 2) else x for x in range (2, num)
for i in range(3, int(x**(1/2))+1, 2) if not (x%i==0)]
产生:
[10, 11, 13, 14, 16, 17, 19]
不确定我哪里出错了,并希望得到一些帮助。事实上,我认为在这种情况下使用函数会更好,但就像我说的那样,我试图理解列表理解及其功能。
答案 0 :(得分:4)
你可以这样做:
[n for n in range(2, num) if n % 2 != 0 and n > 2 and all(n % i != 0 for i in range(3, int(math.sqrt(n)) + 1, 2))]
虽然只是为了它的一个衬垫不一定是好事。 IMO使用像你这样的主要测试器功能更好......
注意:在您的尝试中不起作用的是您修改了外部列表理解的逻辑。您仍然需要[n for n in range(...) if (expression testing if n is prime)]
等结构。
答案 1 :(得分:0)
主要问题是你正在进行复杂的翻译。尝试简化原始条件,以便返回“x if x == 2,else x ...”,就像您已经完成的那样。我只是在这里给你一个领先的暗示;从你已经完成的事情来看,我认为你可以搞清楚。
如果没有,请尝试简化“else”表达式,以便学习该子句的逻辑。然后我相信你会明白的。你做得很好。
答案 2 :(得分:0)
上面的代码中存在逻辑错误
1/2
的计算结果为0,而不是0.5。要做到这一点,要么使用0.5或1 / 2.0或1.0 / 2
此外,它不会照顾2作为一个特例。因为(for i in range(3, int(x**(1/2.0))+1, 2) if not (x%i==0))
未执行
for i in range(3, int(x**(1/2.0))+1, 2) if not (x%i==0)
也是一个逻辑错误,因为只要这个条件为真,它就会导致添加多个条目
正确的方法是
[x for x in range (2, num) if x == 2 or (x > 2 and x % 2 == 1 and len([i for i in range(3, int(x**(1/2.0))+1, 2) if x%i == 0 ])==0)]