2010-06-29 48 views
3

我流一個非常大的集合通過一個腳本,我目前在一個簡單的通話使用ifilter拒絕特定的值,即IFilter的:簡潔的方式來調用與蟒蛇多個謂詞

ifilter(lambda x: x in accept_list, read_records(filename)) 

這是一個謂語,但是現在發生在我身上我應該補充另一個,並且我可能會在未來添加其他人。直接的方法將已經被嵌套一個ifilter電話:

ifilter(lambda x : x not in block_list, 
    ifilter(lambda x: x in accept_list, read_records(filename))) 

我想簡單地把謂詞的綁定功能列表,並使用他們的這一點。雖然這些重複的ifilter調用看起來很難實現(並且可能不是最好的選擇)。也許我可以構造一個調用所有謂詞的單個函數,但是如何儘可能簡潔地(儘管仍然可讀)編寫它?

回答

5

你可以寫以下功能:

def conjoin(*fns): 
    def conjoined(x): 
     for fn in fns: 
      if not fn(x): return False 
     return True 
    return conjoined 

你會然後調用它像這樣:

ifilter(conjoined(lambda x: x not in block_list, lambda x: x in accept_list), 
     read_records(filename)) 

而且你可以實現一個類似disjoin功能 -ing功能結合在一起:

def disjoin(*fns): 
    def disjoined(x): 
     for fn in fns: 
      if fn(x): return True 
     return False 
    return disjoined 

實施它們可能有更好的方法,但必須小心。有人可能會嘗試將每個函數應用到x並使用allany,但這是不可取的,因爲使用它們將需要評估參數上的每個謂詞。這裏介紹的解決方案是令人滿意的短路。

而且,只是爲了好玩,讓我們實現一個invert功能

def invert(fn): 
    return lambda x: not fn(x) 

現在,我們有一個functionally complete一套功能操作功能,並且可以構建任何邏輯運算出來的這些:)

1

我要堅持以下解決方案:

def complex_predicate(x): 
    return x not in block_list and x in accept_list and is_good(x) 

def complex_predicate2(x): 
    return all([x not in block_list, x in accept_list, is_good(x)]) 

然後

ifilter(complex_predicate, read_records(filename)) 

complex_predicate2相同。

但是,我認爲這是一個味道的問題,但。

0

如果只有兩個謂詞,我會拿出以下內容:

ifilter(lambda x: x in accept_list and x not in block_list, read_records(filename)) 

另外,如上所述,如果t這裏有兩個以上的謂詞,最好把所有的謂詞放在特定的函數中。 使用all可以使條件塊更加雜亂(因爲在這種情況下所有謂詞都以逗號分隔)。