2014-01-08 19 views

回答

2

由於processFunc必須是功能,而不是調用一個函數的結果

其實行:

processFunc = collapse and " ".join(s.split()) or s 

將引發NameError因爲s沒有定義。如果s被定義,則取決於collapse是否可以評估爲字符串" ".join(s.split())s

而行:

processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s) 

將評估在功能(lambda s: " ".join(s.split()))如果collapse是真實的,還是功能(lambda s: s)否則。

注意,寫入A and B or C是有點相當於寫入B if A else C,儘管它們是不等效 100%,因爲在if版本僅A小號布爾值是很重要的,以確定所述表達式的結果,而在其他代碼如果A爲真,且B爲假,則結果爲C

你真的應該重新寫行:

processFunc = (lambda s: " ".join(s.split())) if collapse else (lambda s: s) 

雖然在這種特殊情況下因爲所有lambda s爲真and + or形式等同。

你甚至可能會與實際功能代替lambda s到提高可讀性:

def identity(x): 
    return x 

def normalize_spaces(s): 
    return ' '.join(s.split()) 

processFunc = normalize_spaces if collapse else identity 
+0

非常感謝。:) –

0

使用函數推遲表達式的評估,直到稍後的一點。 " ".join(s.split())是一個字符串。 (lambda s: " ".join(s.split()))是一個函數,它在被調用時會返回一個字符串。如果你需要一個函數(也就是說,如果這個對象是你稍後想要調用的東西),你需要這個函數,而不是結果。

在這種情況下,在您定義processFunc時,甚至可能沒有任何s的範圍。該函數已創建,但它會拆分/連接稍後傳遞的字符串。直接執行" ".join(s.split()),您現在需要有s這裏。

0

這是一個非常緊湊的方式分配兩個函數processFunc之一。這裏的lambda這一點不是對任何字符串做任何事情,而是設置一個函數,稍後可以調用它來摺疊或不折疊空格。

如果collapse爲真,則它分配函數lambda s: " ".join(s.split()),這使得processFunc是一個摺疊空白的函數。如果collapse爲假,則它指定一個無操作函數(lambda s: s),在這種情況下,processFunc只是簡單地返回其輸入。

你能等效,也許更清楚,寫行:

def collapseWhitespace(s): 
    return " ".join(s.split()) 

def doNothing(s): 
    return s 

if collapse: 
    processFunc = collapseWhitespace 
else: 
    processFunc = doNothing 
1

在其他形式,它是:

processFunc = (lambda s: " ".join(s.split())) if collapse else (lambda s: s) 

(順便說一句,這種形式的 - 我的測量 - 通常效率更高)

編輯:

我已經看到了很多解釋它的作用 - 但這裏是這個想法背後的基本原理。 實質上,當崩潰是一個全局變量設置一次(命令行或配置),和下面的函數

def processFunc(s): 
    return " ".join(s.split()) if collapse else s 

稱爲無數次,在每個呼叫檢查條件增加了處理開銷 - 這可能是相當大的。將功能分解爲2個功能,評估條件一次並分配功能參考使您的代碼更高性能效率

+0

更重要的是,這種形式*非常容易閱讀! – mgilson

+0

@migilson,我完全同意你的看法!我使用這個表單多次使用字符串賦值 - 並且在計時之後將其更改爲__if .. else__ – volcano