Python 中定義函數有兩種方法,一種是用常規方式 def 定義,函數要指定名字,第二種是用 lambda 定義,不須要指定名字,稱爲 Lambda 函數。html
Lambda 函數又稱匿名函數,匿名函數就是沒有名字的函數,函數沒有名字也行?固然能夠啦。有些函數若是隻是臨時一用,並且它的業務邏輯也很簡單時,就不必非給它取個名字不可。python
比如電影裏面的羣衆演員,每每他們的戲份不多,最可能是陪襯主演,跑跑龍套,他們須要名字嗎?不須要,由於他們僅僅只是臨時出鏡,下次可能就用不着了,因此犯不着費心思給他們每一個人編個號取個名字,畢竟取個優雅的名字是很費勁的事情。編程
先來看個簡單 lambda 函數閉包
>>> lambda x, y : x+y
<function <lambda> at 0x102bc1c80>複製代碼
x 和 y 是函數的兩個參數,冒號後面的表達式是函數的返回值,你能一眼看出這個函數就是是在求兩個變量的和,但做爲一個函數,沒有名字如何使用呢?這裏咱們暫且給這個匿名函數綁定一個名字,這樣使得咱們調用匿名函數成爲可能app
>>> add = lambda x, y : x+y
>>> add
<function <lambda> at 0x102bc2140>
>>> add(1,2)
3複製代碼
它等同於常規函數編程語言
>>> def add2(x, y):
... return x+y
...
>>> add2
<function add2 at 0x102bc1c80>
>>> add2(1,2)
3複製代碼
若是定義匿名函數,還要給它綁定一個名字的話,有點多此一舉,一般是直接使用 lambda 函數。那麼 lamdba 函數的正確使用場景在哪呢?函數式編程
一、函數式編程函數
儘管 Python 算不上是一門純函數式編程語言,但它自己提供了不少函數式編程的特性,像 map、reduce、filter、sorted 這些函數都支持函數做爲參數,lambda 函數就能夠應用在函數式編程中。spa
請看題:一個整數列表,要求按照列表中元素的絕對值大小升序排列,你會怎麼作?思考一分鐘往下看.net
>>> list1 = [3,5,-4,-1,0,-2,-6]
>>> sorted(list1, key=lambda x: abs(x))
[0, -1, -2, 3, -4, 5, -6]複製代碼
排序函數 sorted
支持接收一個函數做爲參數,該參數做爲 sorted 的排序依據,這裏按照列表元素的絕對值進行排序,固然,我也能夠用普通函數來實現:
>>> def foo(x):
... return abs(x)
...
>>> sorted(list1, key=foo)
[0, -1, -2, 3, -4, 5, -6]複製代碼
只不過是這種方式代碼看起來不夠 Pythonic 而已。
二、閉包
閉包自己是一個晦澀難懂的概念,它能夠專門單獨用一篇文章來介紹,不過在這裏咱們能夠簡單粗暴地理解爲閉包就是一個定義在函數內部的函數,閉包使得變量即便脫離了該函數的做用域範圍也依然能被訪問到。
來看一個用 lambda 函數做爲閉包的例子。
>>> def my_add(n):
... return lambda x:x+n
...
>>> add_3 = my_add(3)
>>> add_3(7)
10複製代碼
這裏的 lambda 函數就是一個閉包,在全局做用域範圍中,add_3(7) 能夠正常執行且返回值爲10,之因此返回10是由於在 my_add 局部做用域中,變量 n 的值在閉包的做用使得它在全局做用域也能夠被訪問到。
換成常規函數也能夠實現閉包,只不過是這種方式稍顯囉嗦。
>>> def my_add(n):
... def wrapper(x):
... return x+n
... return wrapper
...
>>> add_5 = my_add(5)
>>> add_5(2)
7複製代碼
那麼是否是任何狀況 lambda 函數都要比常規函數更清晰明瞭呢?看這個例子:
f = lambda x: [[y for j, y in enumerate(set(x)) if (i >> j) & 1] for i in range(2**len(set(x)))]複製代碼
這是一個返回某個集合的全部子集的 lambda 函數,你看明白了嗎?我是很難一眼看出來
zen of python 中有這樣一句話是 Explicit is better than implicit(明瞭勝於晦澀)。記住,若是用 lambda 函數不能使你的代碼變得更清晰時,這時你就要考慮使用常規的方式來定義函數。
5月4日晚上8點,我在CSDN直播《爬蟲入門與實踐》,有興趣的能夠去看看,須要優惠的能夠在公衆號留言,暗號「福利」。
同步發表:foofish.net/lambda.html
公衆號 Python之禪 (id:VTtalk),分享 Python 等技術乾貨