重構過濾器並對映到列表推導

filtermap 函式通常應該由列表推導替換。Guido Van Rossum 在 2005 年的一封公開信中描述了這一點 :

filter(P, S) 幾乎總是像 [x for x in S if P(x)] 一樣更加清晰,這有一個巨大的優勢,即最常見的用法涉及比較的謂詞,例如 x==42,並且定義一個 lambda,這對讀者來說需要更多的努力(加上 lambda 比列表理解)。對於 map(F, S) 來說更是如此。當然,在許多情況下,你可以使用生成器表示式。

以下程式碼行被認為是“ 非 pythonic ”,並且會在許多 python linters 中引發錯誤。

filter(lambda x: x % 2 == 0, range(10)) # even numbers < 10
map(lambda x: 2*x, range(10)) # multiply each number by two
reduce(lambda x,y: x+y, range(10)) # sum of all elements in list

根據我們從前面的引文中學到的東西,我們可以將這些 filtermap 表示式分解為它們的等效列表推導 ; 還從每個函式中刪除 lambda 函式 - 使程式碼在此過程中更具可讀性。

# Filter:
# P(x) = x % 2 == 0
# S = range(10)
[x for x in range(10) if x % 2 == 0]

# Map
# F(x) = 2*x
# S = range(10)
[2*x for x in range(10)]

在處理連結函式時,可讀性變得更加明顯。由於可讀性,一個對映或過濾函式的結果應該作為結果傳遞給下一個; 在簡單的情況下,這些可以用單個列表理解來代替。此外,我們可以很容易地從列表中瞭解我們的過程的結果是什麼,在推斷鏈式 Map 和 Filter 過程時有更多的認知負荷。

# Map & Filter
filtered = filter(lambda x: x % 2 == 0, range(10))
results = map(lambda x: 2*x, filtered)

# List comprehension
results = [2*x for x in range(10) if x % 2 == 0]

重構 - 快速參考

  • 地圖

    map(F, S) == [F(x) for x in S]
    
  • 過濾

    filter(P, S) == [x for x in S if P(x)]
    

其中 FP 是分別轉換輸入值並返回 bool 的函式