簡體   English   中英

函數定義與Lambda表達式

[英]Function definitions vs Lambda expression

鑒於以下兩個片段:

def sex (code):
    return {'m': 'masculino', 'f': 'femenino', '': 'ignorado'} [code]

sex = lambda code: {'m': 'masculino', 'f': 'femenino', '': 'ignorado'} [code]

實際區別是什么? 他們有不同的行為嗎?

最重要的是:一個比另一個更可取嗎?

我之所以這樣問,是因為我在這個論壇中的答案之一( python3-學習搜索,這個非常簡單的示例無法正常工作 ),提供了兩種可能,但又被另一位用戶截斷(“修訂”),刪除了lambda術語。 進行修訂的原因是最后一個選項(lambda表達式)比函數定義 這讓我感到奇怪:

為什么lambda表達式比函數定義更糟糕? 像這樣的特別簡單的。

返回相同結果的lambda和def在功能上沒有區別。 它們完全相同,並且具有相同的字節碼。

>>> def sex (code):
...     return {'m': 'masculino', 'f': 'femenino', '': 'ignorado'} [code]
>>> sex2 = lambda code: {'m': 'masculino', 'f': 'femenino', '': 'ignorado'} [code]
>>> sex.__code__.co_code == sex2.__code__.co_code
True

我會說任何一種編寫函數的方式在一般意義上都是“更糟糕的”是錯誤的。 但是,在您的示例中, def版本更好。 原因是一般來說,lambda的目的是在表達式中簡潔地編寫簡短的匿名函數。 name = lambda: ...沒有真正意義。 如果您要立即為其命名,則沒有理由定義匿名函數。

lambda的要點是,您可以執行someFuncRequiringCallback(lambda x: x+1) ,在此情況下,您不想為函數命名或將其用於someFuncRequiringCallback(lambda x: x+1)情況以外的任何其他操作。 如果確實要在多個上下文中使用函數,則只需使用常規def對其進行定義。

除了BrenBarn出色答案中提供的信息外,您還會發現許多Python程序員堅持始終使用def over lambda ,因此我將嘗試解釋為什么這樣做。

它基本上可以歸結為Python Zen的以下幾行:

應該有一種-最好只有一種-顯而易見的方法。

Guido van Rossum的帖子中對此問題進行了引用(Guido是Python的創建者):

為什么要丟棄lambda? 大多數Python用戶不熟悉Lisp或Scheme,因此名稱令人困惑; 同樣,人們普遍認為lambda可以完成嵌套函數無法完成的工作-我仍然記得勞拉·克雷頓(Laura Creighton)的Aha!-erlebnis,我向她展示了兩者之間沒有任何區別! 即使有了更好的名字,我認為並排選擇兩個選項僅要求程序員考慮做出與他們的程序無關的選擇。 沒有選擇可以簡化思考過程。 而且,一旦map(),filter()和reduce()消失了,就沒有很多地方需要編寫非常短的局部函數了。 我想到了Tkinter回調,但是我發現,無論如何,這些回調通常應該是某些帶有狀態的對象的方法(玩具程序除外)。

它們是相同的,請檢查反匯編的python字節碼

>>> def sex1 (code):
    return {'m': 'masculino', 'f': 'femenino', '': 'ignorado'} [code]

>>> sex2 = lambda code: {'m': 'masculino', 'f': 'femenino', '': 'ignorado'} [code]
>>> dis.dis(sex1)
  2           0 BUILD_MAP                3
              3 LOAD_CONST               1 ('masculino')
              6 LOAD_CONST               2 ('m')
              9 STORE_MAP           
             10 LOAD_CONST               3 ('femenino')
             13 LOAD_CONST               4 ('f')
             16 STORE_MAP           
             17 LOAD_CONST               5 ('ignorado')
             20 LOAD_CONST               6 ('')
             23 STORE_MAP           
             24 LOAD_FAST                0 (code)
             27 BINARY_SUBSCR       
             28 RETURN_VALUE        
>>> dis.dis(sex2)
  1           0 BUILD_MAP                3
              3 LOAD_CONST               1 ('masculino')
              6 LOAD_CONST               2 ('m')
              9 STORE_MAP           
             10 LOAD_CONST               3 ('femenino')
             13 LOAD_CONST               4 ('f')
             16 STORE_MAP           
             17 LOAD_CONST               5 ('ignorado')
             20 LOAD_CONST               6 ('')
             23 STORE_MAP           
             24 LOAD_FAST                0 (code)
             27 BINARY_SUBSCR       
             28 RETURN_VALUE    

甚至他們兩個都有相同的類型

>>> type(sex1)
<type 'function'>
>>> type(sex2)
<type 'function'>

簡單的lambda不一定比嵌套函數差(並且不,這兩個示例之間沒有語法差異),但是這種特殊情況甚至可以更簡單:

sex = {'m': 'masculino', 'f': 'femenino', '': 'ignorado'}

然后,您使用sex.__getitem__

它們具有相同的行為,但主要區別在於lambda是一個表達式,因此不能包含語句。 只要使用得當,lambda不一定比函數定義差。 但是,它們通常僅用於編寫單行函數,因為它們可以執行,即使這實際上使代碼無法讀取也是如此。 例如,考慮以下內容:

sortfilter = lambda a, b, c: sorted(filter(lambda i: i % 2, (i for i in a if i in b)), key=lambda v: c.get(v, v)))

可以用單行lambda編寫,但這是個壞主意!

它有助於區分事物。 如果我定義一個函數,我將從def開始,但是在該函數內部,我通常會使用lambda。

這與用英語寫作是相同的概念。 如果引號引用了引號,您將要更改嵌套引號的外觀。 括號也是如此。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM