閉包

Python SELF TW
等級 13 , 課堂 3
開放

3.1 關於閉包的介紹

閉包是一個可以捕捉其外部作用域中的變量的函數, 即使在這個作用域執行完後。這意味著,閉包可以「記住」來自其外部 作用域的變量值,即使在這個作用域不再活躍時仍然能繼續使用它們。

為了了解閉包如何工作,我們先看看下面的例子:


def outer_function(x):
    def inner_function(y):
        return x + y

    return inner_function
    
closure = outer_function(10)
print(closure(5))  # 輸出: 15

讓我們來解析一下這段程式碼:

外部函數 (outer_function):這個函數接受 參數 x 並定義了一個內部函數 inner_function, 它接受參數 y 並返回 xy 的和。函數 inner_function 並沒有被調用,而只是聲明。

內部函數 (inner_function):這個函數 從 outer_function 返回並內部保持著 x 的值,這是傳遞給 outer_function 的。

閉包:變量 closure 成為了 一個閉包,記住了 x 的值(在這例子中是 10)並且可以 在調用時使用它。

通常,要第一次真正理解閉包的運作並不容易。所以 我們來透過例子加深對閉包的理解。

3.2 使用閉包的例子

創建生成器函數

閉包可以用來創建生成器函數,生成一連串的值。


def make_counter():
    count = 0

    def counter():
        nonlocal count
        count += 1
        return count

    return counter
    
counter = make_counter()
print(counter())  # 輸出: 1
print(counter())  # 輸出: 2
print(counter())  # 輸出: 3

解析:

生成器函數 (make_counter):這個函數創建了 一個變量 count 並返回一個內部函數 counter,它 增加 count 的值並返回它。

閉包:函數 counter 保持著變量 count 的狀態,並能在每次被調用時改變它。

創建配置函數

閉包可以用來創建具有預先定義配置的函數。


def make_multiplier(factor):
    def multiplier(x):
        return x * factor

    return multiplier
    
double = make_multiplier(2)
triple = make_multiplier(3)
    
print(double(5))  # 輸出: 10
print(triple(5))  # 輸出: 15

解析:

配置函數 (make_multiplier):這個函數 接受一個乘數 factor 並返回一個內部函數 multiplier, 它將輸入值乘以 factor

閉包:函數 doubletriple 是閉包, 保持了它們各自的 factor 值並用於 乘法運算。

用參數篩選數據

閉包在創建具有參數的篩選函數時非常有用。


def make_filter(threshold):
    def filter_func(value):
        return value > threshold
        
    return filter_func
    
filter_above_10 = make_filter(10)
data = [5, 10, 15, 20]
filtered_data = list(filter(filter_above_10, data))
print(filtered_data)  # 輸出: [15, 20]

解析:

篩選函數 (make_filter):這個函數接受 一個門檻值 threshold 並返回一個內部函數 filter_func, 它檢查值是否超過門檻。

閉包:函數 filter_func 保存了 threshold 的值並用於篩選數據。

3.3 閉包的優缺點

使用閉包的優勢

封裝狀態:閉包允許在函數中封裝 狀態,從而避免全局變量並提高代碼的可讀性和 可維護性。

靈活性:閉包可以用來創建具有特定配置或行為的 函數,從而使代碼更加靈活和可適應。

函數式編程:閉包是函數式編程中的重要概念, 允許創建高階函數和其他函數式結構。

限制和潛在問題

儘管閉包有很多優勢,但它們也有一些限制:

內存使用:閉包可能會保持對不再使用的 對象的引用,這可能導致內存泄漏。

調試困難:閉包可能會使代碼的調試變得困難, 因為變量的狀態可能不明顯。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION