2017-09-23 163 views
5

lambda表達式我瞭解正常lambda表達式,如困惑在python

g = lambda x: x**2 

然而,對於一些複雜的,我有點困惑他們。例如:

for split in ['train', 'test']: 
    sets = (lambda split=split: newspaper(split, newspaper_devkit_path)) 

def get_imdb(): 
    return sets() 

其中newspaper是一個函數。我在想什麼sets是什麼,爲什麼get_imdb函數可以返回值sets()

感謝您的幫助!

補充: 的代碼實際上是從這裏factory.py

+3

你確定代碼是正確的嗎?每次迭代都要重新賦值'sets'真的很奇怪。 –

+0

我認爲這只是OP創建一個最小范例的嘗試。根據問題本身,這個代碼不是他自己的。 –

回答

2

sets正在被分配一個lambda,它不是真的應該接受輸入,您從調用的方式看到這種輸入。蘭姆達斯一般表現得像正常功能,因此可以分配到像gsets這樣的變量。 sets的定義由一組額外的括號包圍,沒有明顯的原因。你可以忽略那些外面的東西。

Lambdas可以具有與普通函數相同的所有類型的位置,關鍵字和默認參數。 λsets具有名爲split的默認參數。這是一個常見的習慣用法,以確保循環的每次迭代中的sets獲得與該迭代相對應的split的值,而不是所有情況下最後一次迭代中的值。

如果沒有默認參數,split將根據調用時的名稱空間在lambda中進行評估。循環完成後,外部函數的名稱空間中的split將只是該循環的最後一個值。

創建函數對象時立即評估默認參數。這意味着缺省參數split的值將在創建它的循環迭代中的任何位置。

您的示例有點令人誤解,因爲它丟棄了除最後一個之外的所有sets的實際值,從而使默認參數爲lambda無意義。這裏是一個例子,說明如果你保留所有的lambda表達會發生什麼。首先使用默認參數:

 
sets = [] 
for split in ['train', 'test']: 
    sets.append(lambda split=split: split) 
print([fn() for fn in sets]) 

我已經截斷了lambda表達式只是返回它們的輸入參數,用於說明目的。如預期的那樣,此示例將打印['train', 'test']

如果你不這樣做的默認參數同樣的事情,輸出將是['test', 'test']代替:

 
sets = [] 
for split in ['train', 'test']: 
    sets.append(lambda: split) 
print([fn() for fn in sets]) 

這是因爲'test'split值當所有的lambda表達式得到評估。

+0

當我們調用'fn'時,會不會有參數?以'g = lambda x:x ** 2'爲例,我們需要把它叫做g(2),而g()不合理。如果它有默認參數,那麼它看起來沒問題,因爲創建它時已經生成了這些值。但對於沒有缺省參數的那些,我們是否應該在最後一個例子中使用'print([fn(split)for fn in sets])'? –

+1

在最後一個例子中,lambda函數被定義爲'lambda:split',i。即它是'def func():'(不帶參數的函數)。如果lambda函數使用參數,則必須定義e。 G。作爲'lambda x:x ** 2'(你的第一個可以理解的例子) - 在'lambda'和':'之間帶有參數名稱。 – MarianD

0

lambda函數:

func = lambda x: x**2 

幾乎可以等同改寫:

def func(x): 
    return x**2 

使用這兩種方式,你可以調用功能如下:

func(4) 

在你的榜樣,

sets = lambda split=split: newspaper(split, newspaper_devkit_path) 

可以寫成:

def sets(split=split): 
    return newspaper(split, newspaper_devkit_path) 

等都可以稱爲:

sets() 

當你寫下以下內容:

def get_imdb(): 
    return sets() 

你正在定義一個「閉包」。對函數sets的引用保存在get_imdb內,以便在調用get_imdb的任何地方都可以調用該函數。

+0

您沒有解決默認參數的用途,也沒有說明'sets'的最後一個值被丟棄的事實。 'def get_imb():...''不*創建閉包。它只是一個正常的函數調用。 –

0

也許你對split=split部分感到困惑。這與它在常規函數中具有的含義相同:左邊的分割是lambda函數的參數,右邊的分割是默認值,左邊的分割在沒有提供值時會執行。在這種情況下,默認值將是for循環中定義的變量split

所以,回答你的第一個問題(什麼是sets):

sets是其中一個匿名函數(或lambda函數)分配一個變量。這允許通過變量sets來引用和使用lambda函數。

第二個問題(爲什麼sets()可以退回?),我回應:

由於sets是一個變量,充當函數,在調用lambda函數後添加圓括號。因爲沒有給出參數,所以參數split取值'test',這是for循環變量split所採用的最後一個值。這裏值得注意的是,由於sets未在函數get_imdb內部定義,因此解釋程序在get_imdb範圍外尋找sets的定義(並找到引用lambda函數的那個​​定義)。