
認識 Lambda/Closure(3)Python 對 Lambda/Closure 的支援
認識 Lambda/Closure(2)什麼是 Closure? << 前情 在 Python 中可以使用 def max(m, n): return m if m > n else n print(max(10, 3)) # print 10 maximum = max print(maximum(10, 3)) # print 10 如果要在 Python 中建立匿名函式,可以使用 max = lambda m, n: m if m > n else n print(max(10, 3)) # print 10 不同的語言在支援函式或 Lambda 時提供不同的語法。Python 簡明的語法顯然在表達函式上,優於 JavaScript。在以下的對比中,你可以明顯看出兩者在表達函式上的差異性: // 定義函式:JavaScript function max(n, n) { return m > n ? m : n; } # 定義函式:Python def max(m, n): return m if m > n else n // 建立匿名函式:JavaScript function(n, n) { return m > n ? m : n; }; # 建立匿名函式:Python lambda m, n: m if m > n else n 來看看另一個運用 Lambda/Closure 的例子。如果你的函式運用了某個耗時的資源,通常可以考慮將運算的結果加以重用,這是效能調整上的一個考量。方法之一是建立全域資源,並在函式中加以運用。然而,全域資源不是個好的方式。我們可以在函式中準備資源,建立一個 Closure 捕捉他,然後從函式中傳回 Closure。例如: import math def prepare_factor(max): # Creating a prime table is time-consuming. primes = [i for i in range(2, max) if prime[i] == 1] def factor(num): while primes[i] ** 2 <= num: if num % primes[i] == 0: list.append(primes[i]) num //= primes[i] else: i += 1 return factor factor = prepare_factor(1000) print(factor(100)) # print [2, 2, 5, 5] 在上例中,內部函式 到目前為止你可以看到,如果函式是物件,那麼就可以:
不過,Python 的 Closure 有個重大的限制。你沒辦法對閒置變數設值。也就是說,在 Python 中,Closure 捕捉的閒置變數是唯讀的。例如: def func(): x = 10 def getX(): return x def setX(n): x = n # 建立區域變數 x return (gegX, setX) getX, setX = func() getX() # 10 setX(20) getX(10) # still 10 在 Python 中,首次對變數設值時就等同於建立新的區域變數。在上例中,如果呼叫 幸運地,在 Python 3 中,可以使用 def func(): x = 10 def getX(): return x def setX(n): nonlocal x = n return (gegX, setX) getX, setX = func() getX() # 10 setX(20) getX(10) # 20 在上例中, 我們已經看過 JavaScript 與 Python 對 Lambda/Closure 的支援方式。他們都是動態語言。如果使用的是靜態語言,那麼會有哪些要素需要考量?看看現有並且支援 Lambda/Closure 的靜態語言,從中瞭解一些經驗似乎是個不錯的方式。這也是下一篇文章要看的內容,我們會來看看 Scala 如何支援 Lambda/Closure。 |