2017-04-05 33 views
1

編寫斐波那契函數時遇到了這個問題。爲了使它更快,我使用名爲cache的字典來存儲已經計算的數字。所以我寫了爲什麼Python語句'如果東西是None'比'如果不是東西'要快得多?

def fib(n, cache=None): 
    if not cache: 
     cache = {} 
    if n in cache: 
     return cache[n] 
    if n==0 or n==1: 
     return 1 
    else: 
     cache[n] = fib(n-1, cache) + fib(n-2, cache) 
    return cache[n] 

def fib_run(n): 
    start = time.time() 
    fib(n) 
    end = time.time() 
    print("fib_run cost: {}".format(end-start)) 

我呼籲fib_run(30),輸出爲fib_run cost: 0.8419640064239502,它只是作爲不帶緩存的功能緩慢。 但是,當我在功能fib2中將if not cache:更改爲if cache is None:時,它的工作速度更快。

def fib2(n, cache=None): 
    if cache is None: 
     cache = {} 
    if n in cache: 
     return cache[n] 
    if n==0 or n==1: 
     return 1 
    else: 
     cache[n] = fib2(n-1, cache) + fib2(n-2, cache) 
    return cache[n] 

def fib2_run(n): 
    start = time.time() 
    fib2(n) 
    end = time.time() 
    print("fib_run cost: {}".format(end-start)) 

>>> fib2_run(30) 
fib2_run cost: 2.6226043701171875e-05 

我想知道爲什麼兩種方法之間存在如此巨大的差異(我認爲它們在早期是一樣的)。謝謝。

+2

'緩存None'是身份檢查。 'not cache'是字典的空白檢查。這些是引擎蓋下的兩種不同的操作。 –

+0

你的意思是空虛檢查花費更多的時間?你能告訴我爲什麼嗎? –

回答

1

這裏的問題不是is None VS not cache的表現,相反,它是if cache is NoneTrue僅僅在fib2if not cacheTrue即使cache == {}fib第一次調用。 「空」的集合評估爲因此Falsenot一個空的集合會True

>>> not {} 
True 

所以你在做額外的工作(以{}分配緩存),即使在情況下,cache已經等於{}

一般來說,這些操作在性能上非常相似,一個是簡單的身份檢查,而另一個是基於值的單數(對於字典而言,基於__len__的結果,如果我不是錯誤)。

+0

這有助於很多,謝謝。 –

+0

@KasheemLew不客氣,很高興我能幫到你! :-) –

0

在第一種情況下,緩存總是空的!難怪你獲得與沒有緩存的功能相同的時間。所有你需要的是打印看看會發生什麼。

if not cache: 
#if cache is None: 
    print(n, "No cache!") 
    cache = {} 

如上所述,空集合評估爲false。在遞歸調用中,if not cache總是如此,你創建一個新的字典,你發送一個級別在下面,這又被評估爲錯誤的,等等。緩存中永遠不會有單個條目。

(做額外的工作,甚至在緩存中已經等於{}的情況下,如上面提到的,是一個時間的操作。不應該花費更大的ñ東西)

相關問題