我正在尝试使用this方法生成素数列表。我需要遍历每个数字2 ... n并检查它是2 ... n的倍数。出于某种原因,错误的列表似乎正在被修改。
import sys
import argparse
import math
parser = argparse.ArgumentParser(description='find the largest prime factor of a number')
parser.add_argument('n', type=int, help='number')
args = parser.parse_args()
sieve = []
for i in range(2,args.n+1): sieve.append(i) # tried int(i)
copy1 = sieve # tried making extra copies. . .
copy2 = sieve
copy3 = sieve
#print int(math.sqrt(args.n))
for index, i in enumerate(copy1):
#print index, i
for ii in copy2:
#print ii
if i % ii == 0:
sieve[index]= None
print sieve
我收到以下错误:
Traceback (most recent call last):
File "3.py", line 22, in <module>
if i % ii == 0: TypeError: unsupported operand type(s) for %:
'int' and 'str'
答案 0 :(得分:7)
你没有制作副本。您正在使用引用,因此copy1
,copy2
和copy3
都引用相同的列表 - sieve
。如果要复制,请使用:
copy1 = sieve[:]
将创建sieve
的副本并将其分配给copy1
。
答案 1 :(得分:2)
您需要使用
copy1 = sieve[:] # tried making extra copies. . .
copy2 = sieve[:]
copy3 = sieve[:]
实际复制列表。否则,您只需将引用复制到列表中。
>>> a = [1,2]
>>> b = a
>>> c = a[:]
>>> b[0] = 0
>>> c[0] = 3
>>> a
[0, 2]
>>> b
[0, 2]
>>> c
[3, 2]
答案 2 :(得分:2)
copy1 = sieve
copy2 = sieve
copy3 = sieve
这些不是他们参考的副本。
primes = [2,3,5,7]
def is_prime(n):
if n in primes:
return True
for item in primes:
if n % item == 0:
return False
return True
assert is_prime(4) == False
assert is_prime(29) == True
assert is_prime(65) == False
是一种很好的筛选方法
更多单元测试,因为它很有趣
true_primes = [int(item) for item in '11,13,17,19,23,29,31,37,41,43,47'.split(',')]
for item in xrange(10, 50):
if is_prime(item) == True:
assert item in true_primes
else:
assert item not in true_primes
答案 3 :(得分:2)
Python具有引用语义。通常,a = b
会使名称a
引用名称b
当前所引用的相同值。它不会创建或存储新值。
您可以使用上面提到的[:]技巧克隆列表。复制事物的更通用的解决方案是使用copy
模块。
但是,优秀的Python代码通常不需要经常显式复制内容。您应该熟悉使用列表推导来创建现有序列的“修改版本”。例如,我们可以实施筛子(也展示其他一些东西):
import sys, argparse, math, itertools
parser = argparse.ArgumentParser(description='find the largest prime factor of a number')
parser.add_argument('n', type=int, help='number')
args = parser.parse_args()
# Using a loop over a 'range' to fill a list with increasing values is silly, because
# the range *is* a list of increasing values - that's how the 'for i in ...' bit works.
sieve = range(2, args.n + 1)
# We don't need to remember the original loop at all.
# Instead, we rely on each iteration of the sieve putting a new prime at the beginning.
for index in itertools.count(): # Counting upward,
if index >= len(sieve): break # until we run out of elements,
prime = sieve[index] # we grab the next prime from the list,
sieve = [x for x in sieve if x == prime or x % prime != 0] # and sieve the list with it.
# Of course, we can optimize that by checking that prime < sqrt(args.n), or whatever.
print sieve
答案 4 :(得分:1)
我无法测试这个,因为我没有Python 3.2的副本(argparse
是Python 3.2中的新内容),但是有两个明显的事情浮现在脑海中:
首先,您需要执行sieve.append(int(i))
。
其次,你没有复制筛子,你只是创建一个对同一个列表的新引用。要制作副本,您需要
copy1 = sieve[:]