简体   繁体   English

Scope 列表中的 Python - Project Euler 007

[英]Scope of lists in Python - Project Euler 007

first question here.这里的第一个问题。 I am trying to learn python by stepping through project euler, and I've run into a roadblock.我正在尝试通过逐步完成项目 euler 来学习 python,但我遇到了障碍。 The following method (returns a list of prime factors) works fine for a single call:以下方法(返回主要因素列表)适用于单个调用:

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

However when I use it in a loop, like so (this method may not be complete yet, currently results in infinite loop since more primes cannot be found):但是,当我在循环中使用它时,就像这样(这种方法可能还不完整,目前导致无限循环,因为找不到更多的素数):

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

The result is that the first loop returns [2], the next returns [2, 3], and so on, appending the new results to the list that I Wanted to have been empty on the first recursive call.结果是第一个循环返回 [2],下一个循环返回 [2, 3],依此类推,将新结果附加到我希望在第一次递归调用时为空的列表。 It seems that my list is persisting, but I'm not sure exactly why?似乎我的列表仍然存在,但我不确定为什么? I read Python Class scope & lists as well which gives me some clues but the recursion complicates it more.我还阅读了 Python Class scope 和列表,这给了我一些线索,但递归更复杂。

Recursive also means I cannot simply assign an empty set to it either.递归也意味着我也不能简单地为它分配一个空集。 Coming from a C++ background, my expectation was that the primeFactors variable should be reinitialized each time the function is called from my program.来自 C++ 背景,我的期望是每次从我的程序中调用 function 时都应该重新初始化 primeFactors 变量。 Still a baby snake here.这里还是一条小蛇。

EDIT: This is the iterative version of findPrimeFactors I wrote.编辑:这是我写的 findPrimeFactors 的迭代版本。 I know it is not optimal - but I would like to at least make it efficient enough to meet Project Euler's 1 minute rule.我知道这不是最优的——但我想至少让它足够高效以满足欧拉计划的 1 分钟规则。 Any suggestions for improvement or clarity are appreciated.任何改进或清晰的建议表示赞赏。

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

The default value of primeFactors is being shared between calls, so when you change it, it stays changed for future calls. primeFactors的默认值在调用之间共享,因此当您更改它时,它会保持更改以供将来调用。

Example:例子:

def foo(bar = []):
    bar.append(1)
    return bar

print foo()
print foo()

Output: Output:

[1]
[1, 1]

You should return a new list instead of changing the default:您应该返回一个新列表,而不是更改默认值:

def foo(bar = []):
    return bar + [1]

print foo()
print foo()

Output: Output:

[1]
[1]

As mentioned by hammar, the default value is only created once, when the function is defined, and shared between calls.正如 hammar 所述,默认值仅在定义 function 时创建一次,并在调用之间共享。

The usual way around that is to use a marker value as the default:通常的方法是使用标记值作为默认值:

def findPrimeFactors(num, primeFactors=None):
    if primeFactors is None:
        primeFactors = []
    ...

Off-topic, but your function findPrimeFactor() will recurse once for every prime factor found.题外话,但您的 function findPrimeFactor()将为找到的每个素数因子递归一次。 Python doesn't do tail call removal, so you should probably rewrite this using iteration instead of recursion. Python 不会删除尾调用,因此您可能应该使用迭代而不是递归来重写它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM