python高階函數中一個容易犯的錯

問題

python對函數式編程有必定的支持,具體表如今高級函數,map,reduce,filter,partial function等幾個方面。在應用函數式編程中,須要關注函數式編程中的變量不變性,惰性計算等原則,不然容易踩到坑。python

def f():
   def num_gen():
       x = 2
       while True:
           yield x
           x+=1
   l=num_gen()
   while True:
       n = next(l)
       yield n
       l = filter(lambda x:x%n!=0,l)
primes = f()
for i in primes:
    print(i)

這段代碼本意在於返回一個素數列表,但實際在運行中返回的並非想要的。究其緣由,在於filter的惰性計算以及lambda匿名函數的閉包特性。上面的代碼中,n是一個變量,lambda匿名函數只有在next(f())時纔會真正調用,而此時,n的值已是當前n的值,而不是以前的值了,好比9,應當是3的倍數,但此時n的值並非3,致使9%n>0成立。編程

要修改這段代碼,一個方法是利用lambda的閉包,避開n變量,生成一個和n無關的函數。閉包

def f():
   def g(n):
       return lambda x:x%n!=0
   def num_gen():
       x = 2
       while True:
           yield x
           x+=1
   l = num_gen()
   while True:
       n = next(l)
       yield n
       l = filter(g(n),l)
primes = f()
for i in primes:
    print(i)

這樣修改後,g(n)是實時調用的,返回一個和n無關的函數,這樣在next惰性調用時,就不會出錯。函數式編程

總結

相似的錯誤在返回函數的高階函數中也容易出錯,若是返回的函數和一個變量綁定了,就會出現問題,解決的方法都是同樣,增長一個閉包函數,使得返回函數和變量無關。函數

相關文章
相關標籤/搜索