2009-09-23 36 views
6

這是matplotlib中csv2rec的源代碼這個python函數代碼如何工作?

如果函數的唯一參數是'func,default',該函數如何工作?

def with_default_value(func, default): 
    def newfunc(name, val): 
     if ismissing(name, val): 
      return default 
     else: 
      return func(val) 
    return newfunc 

ISMISSING需要一個名稱和一個值,並且確定該行應該以numpy的陣列被掩蔽。

func將是str,int,float或dateparser ......它將轉換數據。也許不重要。我只是想知道如何得到一個'名字'和'價值'

我是一個初學者。感謝任何2cents!我希望得到足夠的幫助別人!

+1

不應該有像「如果ISMISSING」的空間? – recursive 2009-09-23 02:02:23

回答

8

with_default_value功能是什麼通常稱爲(不準確)的「封閉」(從技術上說,關閉是相當的功能得到恢復,這裏newfunc - 見例如here)。更一般地說,with_default_value是一個高階函數(「HOF」):它將一個函數(func)作爲參數,它還返回一個函數(newfunc)作爲結果。

我見過的答案與裝飾概念混淆這一點,並在Python,這絕對不是的情況下構建 - 尤其是因爲你提到func經常是內置的,例如int。裝飾者也是高階函數,但更具體的是:裝飾者返回裝飾的「富集的」,它們的功能參數的版本(其必須是隻參數 - 通過功能/閉合嵌套多一個電平中獲得「與參數裝飾」,通過給予裝飾HOF多個參數不) ,它被重新分配給完全相同的名稱作爲函數參數(因此通常具有相同的簽名 - 使用裝飾否則將非常奇特,非地道,不可讀,等等)。

所以,不要裝飾,這絕對無關的情況下,並專注於newfunc關閉。詞彙嵌套函數可以引用(儘管不重新綁定)封閉函數的所有局部變量名稱(包括參數名稱,因爲參數是局部變量) - 這就是爲什麼它被稱爲閉包:它是「封閉」這些「自由變量」。在這裏,newfunc可以參考funcdefault - 確實如此。

高階函數在Python中是非常自然的事情,特別是因爲函數是第一類對象(所以沒有什麼特別的事情需要做,以將它們作爲參數傳遞,將它們作爲函數值返回,或者甚至將它們存儲在列表或其他容器等),函數和其他類型的對象之間沒有名稱空間的區別,僅僅因爲提及的函數等等而沒有自動調用函數(這很難 - 有點難,或者更難,取決於 - 在其他語言中,確實吸引了很多這類的區別)。在Python中,提到一個函數就是 - 提及;只有當函數對象(通過名字或其他名稱引用)後面跟有括號時纔會發生CALL。

這是對所有有這個例子 - 請不要隨意修改你的問題,在這裏評論等,如果有,你留在有關懷疑其他一些具體的方面!

編輯:因此OP在評論中有禮貌地要求提供更多關閉工廠的例子。這裏有一個 - 想象一些抽象的一種GUI工具包的,而你要做的:

for i in range(len(buttons)): 
    buttons[i].onclick(lambda: mainwin.settitle("button %d click!" % i)) 

但這不工作的權利 - 在lambdai是後期綁定的,所以在一個時間按鈕被點擊i的值總是將成爲最後按鈕的指數,無論是點擊哪一個。有多種可行的解決方案,但關閉工廠是一個優雅的可能性:

def makeOnclick(message): 
    return lambda: mainwin.settitle(message) 

for i in range(len(buttons)): 
    buttons[i].onclick(makeOnClick("button %d click!" % i)) 

在這裏,我們使用了封閉工廠調整的變量綁定時間 - )在一個特定的形式或其他形式,這是一種封閉工廠非常常見的用例。

+0

我想我糾正了。感謝您的區別。那麼這個HOF怎麼會被調用呢? – dcrosta 2009-09-23 02:49:57

+0

@dcrosta,我沒有這個成語的正式名稱 - 就像大多數HOFs返回閉包一樣,我只是把它看作是實現一個函數工廠的一種便捷方式。 – 2009-09-23 03:02:37

+0

偉大的回答,那是一場戰鬥,首先我認爲其他人有它,然後你進來的觸地!謝謝,我想我們都學到了一些東西!我想知道你有沒有其他的例子?只是好奇。不用擔心,如果它太難找到一個/做一個。 – Pete 2009-09-23 17:31:22

0

這是一個返回另一個函數的函數。 namevalue是返回函數的參數。

6

這是一個Python裝飾器 - 基本上是一個函數包裝器。 (閱讀所有關於PEP 318裝飾 - http://www.python.org/dev/peps/pep-0318/

如果你看看通過代碼,你可能會發現這樣的事情:

def some_func(name, val): 
    # ... 
some_func = with_default_value(some_func, 'the_default_value') 

這個裝飾的意圖似乎如果提供一個默認值名稱或val參數缺失(假設它們設置爲None)。

+0

沒錯,除了新的代碼通常會看起來更像: @with_default_value(some_func, 'the_default_value') 高清some_func(姓名,VAL): #... – 2009-09-23 02:31:10

+0

我想如果你使用@語法(前函數定義),你必須有一個裝飾器工廠(而這是一個純粹的deorator - 2級深)。裝飾工廠可以接受參數,但不需要。除非3.x – dcrosta 2009-09-23 02:33:41

+0

@dcrosta發生了變化:我不這麼認爲。我一直在使用兩個語法與裝飾器互換,沒有不良影響2.X – priestc 2009-09-23 02:52:27

1

至於爲什麼它的工作原理:

with_default_value返回一個函數對象,它基本上會是嵌套newfunc的副本,用「功能」調用和默認值與任何傳遞給substited with_default_value。

如果有人「富= with_default_value(巴,3)」,返回值基本上將是一個新的功能:

def foo(name, val): 
    ifismissing(name, val): 
     return 3 
    else: 
     return bar(val) 

這樣你就可以採取的返回值,並調用它。