Python匿名函數lambda說明及示例 字典數字鍵排序

匿名函數lambda, 你搞清楚 了嗎?

lambda 函數 形式

lambda 表達式(有時稱爲 lambda 構型)被用於創建匿名函數。
匿名函數 一般形式

# 以下表達式 會產生一個函數對象
lambda arguments: expression

該未命名對象的行爲類似於用以下方式定義的函數:
函數形式

def <lambda>(arguments):
    return expression

通過這個形式, 基本上就知道如何使用了, 以及各個位置的作用
注意
注意通過 lambda 表達式創建的函數不能包含語句或標註

示例:

場景一

<節錄自Python中文官方文檔>

可以用 lambda 關鍵字來創建一個小的匿名函數。這個函數返回兩個參數的和: lambda a, b: a+b 。Lambda函數可以在需要函數對象的任何地方使用。它們在語法上限於單個表達式。從語義上來說,它們只是正常函數定義的語法糖。與嵌套函數定義一樣,lambda函數可以引用所包含域的變量:

>>> def make_incrementor(n):
...     return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43

上面的例子使用一個lambda表達式來返回一個函數。另一個用法是傳遞一個小函數作爲參數:

>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]

場景二

有一個鍵爲字符串格式的數字的字典, 需要按照數字的大小從小到大進行排序

test_dict = {'2': '2', '6': '0', '5': '5', '4': '1', '3': '4', '1': '2'}
# lambda 示例  可通過sorted reverse設置升序 還是降序
print(dict(sorted(test_dict.items(), key=lambda x: int(x[0]))))
# 錯誤示例
print(dict(sorted(test_dict.items())))

# 結果輸出
{'1': '2', '2': '2', '3': '4', '4': '1', '5': '5', '6': '0'}
{'1': '2', '2': '2', '3': '4', '4': '1', '5': '5', '6': '0'}

# 對於錯誤示例,大家可以看到結果是一樣的。那你測試一下下面的示例
test_dict = {'1': ['2', '2', '0'], '4': ['0', '1', '1'], '3': ['4', '4', '4'], '6': ['0', '0', '2'], '2': ['2', '2', '2'], '5': ['5', '5', '5']}

使用建議

<節錄自Python中文官方文檔>

需要編寫很小的函數, 且Python未內置該方法

如有Python內置的類似函數, 不建議用lambda。內置的效率會更高
編寫函數式風格程序時,你會經常需要很小的函數,作爲謂詞函數或者以某種方式來組合元素。

如果合適的 Python 內置的或者其他模塊中的函數,你就一點也不需要定義新的函數:

stripped_lines = [line.strip() for line in lines]
existing_files = filter(os.path.exists, file_list)

如果不存在你需要的函數,你就必須自己編寫。一個編寫小函數的方式是使用 lambda 表達式。lambda 接受一組參數以及組合這些參數的表達式,它會創建一個返回表達式值的匿名函數:

adder = lambda x, y: x+y

print_assign = lambda name, value: name + ‘=’ + str(value)
另一種替代方案就是通常的使用 def 語句來定義函數:

def adder(x, y):
    return x + y

def print_assign(name, value):
    return name + '=' + str(value)

哪一種更受青睞呢?這是一個風格問題;我通常的做法是避免使用 lambda。

我這麼偏好的一個原因是,lambda 能夠定義的函數非常受限。函數的結果必須能夠作爲單獨的表達式來計算,這意味着你不能使用多路 if... elif... else 比較,或者 try... except語句。如果你嘗試在 lambda 語句中做太多事情,你最終會把表達式過於複雜以至於難以閱讀。你能快速的說出下面的代碼做了什麼事情嗎?:

import functools
total = functools.reduce(lambda a, b: (0, a[1] + b[1]), items)[1]

你可以弄明白,不過要花上時間來理清表達式來搞清楚發生了什麼。使用一個簡短的嵌套的 def 語句可以讓情況變得更好:

import functools
def combine(a, b):
    return 0, a[1] + b[1]

total = functools.reduce(combine, items)[1]

如果我僅僅使用一個 for 循環會更好:

total = 0
for a, b in items:
    total += b

或者使用內置的 sum() 和一個生成器表達式:

total = sum(b for a, b in items)

許多使用functools.reduce()的情形可以更清晰地寫成 for 循環的形式。

Fredrik Lundh 曾經建議以下一組規則來重構 lambda 的使用:

  • 寫一個 lambda 函數。
  • 寫一句註釋來說明這個 lambda 究竟幹了什麼。
  • 研究一會這個註釋,然後想出一個抓住註釋本質的名字。
  • 用這個名字,把這個 lambda 改寫成 def 語句。
  • 把註釋去掉。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章