簡體   English   中英

Scope 列表中的 Python - Project Euler 007

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

這里的第一個問題。 我正在嘗試通過逐步完成項目 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 和列表,這給了我一些線索,但遞歸更復雜。

遞歸也意味着我也不能簡單地為它分配一個空集。 來自 C++ 背景,我的期望是每次從我的程序中調用 function 時都應該重新初始化 primeFactors 變量。 這里還是一條小蛇。

編輯:這是我寫的 findPrimeFactors 的迭代版本。 我知道這不是最優的——但我想至少讓它足夠高效以滿足歐拉計划的 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

primeFactors的默認值在調用之間共享,因此當您更改它時,它會保持更改以供將來調用。

例子:

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

print foo()
print foo()

Output:

[1]
[1, 1]

您應該返回一個新列表,而不是更改默認值:

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

print foo()
print foo()

Output:

[1]
[1]

正如 hammar 所述,默認值僅在定義 function 時創建一次,並在調用之間共享。

通常的方法是使用標記值作為默認值:

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

題外話,但您的 function findPrimeFactor()將為找到的每個素數因子遞歸一次。 Python 不會刪除尾調用,因此您可能應該使用迭代而不是遞歸來重寫它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM