这里的第一个问题。我试图通过逐步执行项目euler来学习python,我遇到了障碍。以下方法(返回素数因子列表)适用于单个调用:
def findPrimeFactors(num, primeFactors = []):
'''Find the prime factors of an arbitrary positive integer
input: num to factorize
returns: a list containing the prime factors of the number
'''
pIndex = 2
while (num >= pIndex):
if num % pIndex == 0:
num /= pIndex
primeFactors.append(pIndex)
return FindPrimes.findPrimeFactors(num, primeFactors)
else:
pIndex += 1
return primeFactors
然而,当我在循环中使用它时,这样的方法(此方法可能尚未完成,目前导致无限循环,因为无法找到更多的素数):
def countPrimes(n = 1001):
'''find n amount of unique primes ascending
input: number of primes to find
returns: list of n primes starting from 2 '''
primes = []
i = 2
while len(primes) < n:
primeFactors = FindPrimes.findPrimeFactors(i)
print(primeFactors) #verify method behavior
if len(primeFactors) is 1:
primes.append(primeFactors[0])
i += 1
return primes
结果是第一个循环返回[2],下一个循环返回[2,3],依此类推,将新结果附加到我希望在第一个递归调用中为空的列表中。似乎我的名单仍然存在,但我不确定为什么?我也阅读了Python Class scope & lists,它给了我一些线索,但递归使它复杂化了。
递归也意味着我不能简单地为它分配一个空集。来自C ++背景,我的期望是每次从我的程序调用函数时都应该重新初始化primeFactors变量。还是小蛇在这里。
编辑:这是我写的findPrimeFactors的迭代版本。我知道这不是最优的 - 但我希望至少能够有效地满足Project Euler的1分钟规则。任何改进或明确的建议都值得赞赏。
PRIMES = [2,3,5,7,11,13,17,19]
import math
class FindPrimes():
'''V2 iterative'''
def findPrimeFactors(n, primeFactors = None):
'''Find the prime factors of an arbitrary positive integer
input: num to factorize
returns: a list containing the prime factors of the number
'''
if primeFactors is None:
primeFactors = []
num = n
ceil = math.sqrt(n) #currently unused
global PRIMES
knownPrimes = PRIMES
#check known primes for divisors first, then continue searching for primes by brute force
while True:
factorFound = False
for prime in knownPrimes:
if num % prime == 0:
primeFactors.append(prime)
num /= prime
factorFound = True
break #ensure that the list returned has ascending primes
if not factorFound:
break
#once attempts have been made to reduce using known primes
#search for new primes if the number is not fully reduced
i = knownPrimes[-1] + 2
while num != 1:
if num % i == 0:
knownPrimes.append(i)
primeFactors.append(i)
num /= i
i += 2
return primeFactors
def countPrimes(n = 10001):
'''find n amount of unique primes ascending
input: number of primes to find
returns: list of n primes starting from 2 '''
primes = []
i = 2
while len(primes) < n:
primeFactors = FindPrimes.findPrimeFactors(i)
if len(primeFactors) == 1:
primes.append(primeFactors[0])
#print(primeFactors[-1])
i += 1
print(len(primes))
return primes
nth = 10001
print(FindPrimes.countPrimes(nth)[nth-1]) #print the largest prime found
答案 0 :(得分:3)
答案 1 :(得分:1)
默认值primeFactors
在呼叫之间共享,因此当您更改呼叫时,它会保持更改以供将来呼叫使用。
示例:
def foo(bar = []):
bar.append(1)
return bar
print foo()
print foo()
输出:
[1]
[1, 1]
您应该返回一个新列表,而不是更改默认值:
def foo(bar = []):
return bar + [1]
print foo()
print foo()
输出:
[1]
[1]
答案 2 :(得分:1)
如hammar所述,默认值仅在定义函数时创建一次,并在调用之间共享。
通常的方法是使用标记值作为默认值:
def findPrimeFactors(num, primeFactors=None):
if primeFactors is None:
primeFactors = []
...
偏离主题,但是对于找到的每个素数因子,您的函数findPrimeFactor()
将递归一次。 Python不执行尾调用删除,因此您应该使用迭代而不是递归来重写它。