Python Изменение неправильного списка?
-
30-09-2019 - |
Вопрос
Я пытаюсь создать список простых чисел, используя это метод. Мне нужно верить каждый номер 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'
Решение
Вы не делаете копии. Вы используете ссылки, так copy1
, copy2
, а также copy3
Все относятся к одному и тому же списку - sieve
. Отказ Если вы хотите скопировать, использовать:
copy1 = sieve[:]
который создаст копию sieve
и назначить его copy1
.
Другие советы
Вам нужно использовать
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]
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
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
Я не мог проверить это, потому что у меня нет копии Python 3.2 (argparse
Новый в Python 3.2), но на ум приходит две очевидные вещи:
Во-первых, вам нужно сделать sieve.append(int(i))
.
Во-вторых, вы не делаете копию сита, вы просто создаете новую ссылку на тот же список. Сделать копию, вам нужно
copy1 = sieve[:]