我正在尝试创建一个小于或等于给定数字的所有素数的列表。我成功地使用了for循环。我试图使用python实现相同的列表理解。但我的输出有一些意想不到的值。
这是我的代码..
pr=[2]
pr+=[i for i in xrange(3,num+1) if not [x for x in pr if i%x==0]]
其中num
是我从用户那里获得的数字。
的上述代码的输出
num=20 is this: [2, 3, 5, 7, 9, 11, 13, 15, 17, 19]
我很困惑为什么输出中有9和15。我在这里做错了什么?
答案 0 :(得分:4)
在您的整个列表理解完成之前,您的列表pr
不会更新。这意味着您的列表只包含2,因此每个可分为2的数字不在列表中(如您所见)。每当找到新的素数时,都应该更新列表。
答案 1 :(得分:4)
它根本不起作用。列表推导是分开评估的,所以你可以这样想象:
"A"
在评估pr = [2]
tmp = [i for i in xrange(3,num+1) if not [x for x in pr if i%x==0]]
pr += tmp
时,tmp
仅包含pr
,因此您只需检查一个数字是否可被2整除(即如果它是偶数)。这就是为什么你得到所有不均匀的数字。
你根本无法使用列表推导来解决这个问题>>
†不是很好,但是很丑陋且非常黑客,通过滥用你可以在列表理解中调用函数:
2
这会滥用列表推导,并且基本上会为您添加到pr = [2]
[pr.append(i) for i in xrange(3,num+1) if not [x for x in pr if i%x==0]]
print(pr) # [2, 3, 5, 7, 11, 13, 17, 19]
的每个素数收集None
值。所以它基本上就像你的正常for循环,除了我们不必要地在列表中收集pr
值...所以你应该让自己使用换行符并使用正常的循环。
答案 2 :(得分:1)
这是因为pr += [...]
的评估大致如下:
pr = [2]
tmp = [i for i in xrange(3,num+1) if not [x for x in pr if i%x==0]]
pr.extend(tmp)
因此,在生成tmp
时,pr
的内容保持不变([2]
)。
我会选择这样的功能:
>>> import itertools
>>> def primes():
... results = []
... for i in itertools.count(2):
... if all(i%x != 0 for x in results):
... results.append(i)
... yield i
...
# And then you can fetch first 10 primes
>>> list(itertools.islice(primes(), 10))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
# Or get primes smaller than X
>>> list(itertools.takewhile(lambda x: x < 50, primes()))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
请注意,使用all
比创建数组和测试它是否为空更有效。