Python 支援一種有趣的文法,它允許你快速定義單行的最小函數。這些叫做 lambda 的函數,是從 Lisp 借用來的,可以用在任何需要函數的地方。 例 4.20. lambda 函數介紹
>>> def f(x):... return x*2... >>> f(3)6>>> g = lambda x: x*2 >>> g(3)6>>> (lambda x: x*2)(3) 6
|
這是一個 lambda 函數,完成同上面普通函數相同的事情。注意這裡的簡短的文法:在參數列表周圍沒有括弧,而且忽略了 return 關鍵字 (隱含存在,因為整個函數只有一行)。而且,該函數沒有函數名稱,但是可以將它賦值給一個變數進行調用。 |
|
使用 lambda 函數時甚至不需要將它賦值給一個變數。這可能不是世上最有用的東西,它只是展示了 lambda 函數只是一個內嵌函式。 |
總的來說,lambda 函數可以接收任意多個參數 (包括選擇性參數) 並且返回單個運算式的值。lambda 函數不能包含命令,包含的運算式不能超過一個。不要試圖向 lambda 函數中塞入太多的東西;如果你需要更複雜的東西,應該定義一個普通函數,然後想讓它多長就多長。
|
| lambda 函數是一種風格問題。不一定非要使用它們;任何能夠使用它們的地方,都可以定義一個單獨的普通函數來進行替換。我將它們用在需要封裝特殊的、非重用代碼上,避免令My Code充斥著大量單行函數。 |
4.7.1. 真實世界中的 lambda 函數
apihelper.py 中的 lambda 函數:
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
注意這裡使用了 and-or 技巧的簡單形式,它是沒問題的,因為 lambda 函數在布爾環境中總是為真。(這並不意味這 lambda 函數不能返回假值。這個函數對象的布爾值為真;它的傳回值可以是任何東西。)
還要注意的是使用了沒有參數的 split 函數。你已經看到過它帶一個或者兩個參數的使用,但是不帶參數它按空白進行分割。 例 4.21. split 不帶參數
>>> s = "this is\na\ttest" >>> print sthis isatest>>> print s.split() ['this', 'is', 'a', 'test']>>> print " ".join(s.split()) 'this is a test'
|
這是一個多行字串,通過使用逸出字元的定義代替了三重引號。\n 是一個斷行符號,\t 是一個定位字元。 |
|
不帶參數的 split 按照空白進行分割。所以三個空格、一個斷行符號和一個定位字元都是一樣的。 |
|
通過 split 分割字串你可以將空格統一化;然後再以單個空格作為分隔字元用 join 將其重新串連起來。這也就是 info 函數將多行 doc string 合并成單行所做的事情。 |
那麼 info 函數到底用這些 lambda 函數、split 函數和 and-or 技巧做了些什麼呢。
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
processFunc 現在是一個函數,但是它到底是哪一個函數還要取決於 collapse 變數。如果 collapse 為真,processFunc(string) 將壓縮空白;否則 processFunc(string) 將返回未改變的參數。
在一個不很健壯的語言中實現它,像 Visual Basic,你很有可能要建立一個函數,接受一個字串參數和一個 collapse 參數,並使用 if 語句確定是否壓縮空白,然後再返回相應的值。這種方式是低效的,因為函數可能需要處理每一種可能的情況。每次你調用它,它將不得不在給出你所想要的東西之前,判斷是否要壓縮空白。在 Python 中,你可以將決策邏輯拿到函數外面,而定義一個裁減過的 lambda 函數提供確切的 (唯一的) 你想要的。這種方式更為高效、更為優雅,而且很少引起那些令人討厭 (哦,想到那些參數就頭昏) 的錯誤。 lambda 函數進一步閱讀 Python Knowledge Base 討論了使用 lambda 來間接調用函數。 Python Tutorial 示範了如何從一個 lambda 函數內部訪問外部變數。(PEP 227 解釋了在 Python 的未來版本中將如何變化。) The Whole Python FAQ 有關於令人模糊的使用 lambda 單行語句的例子。 from: http://woodpecker.org.cn/diveintopython/power_of_introspection/lambda_functions.html