Python修改错误列表?

时间:2010-12-02 16:10:55

标签: python list primes nested-loops

我正在尝试使用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'

5 个答案:

答案 0 :(得分:7)

你没有制作副本。您正在使用引用,因此copy1copy2copy3都引用相同的列表 - 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[:]