简洁的方式来调用与蟒蛇多个谓词

问题描述:

我流一个非常大的集合通过一个脚本,我目前在一个简单的通话使用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调用看起来很难实现(并且可能不是最好的选择)。也许我可以构造一个调用所有谓词的单个函数,但是如何尽可能简洁地(尽管仍然可读)编写它?

你可以写以下功能:

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一套功能操作功能,并且可以构建任何逻辑运算出来的这些:)

我要坚持以下解决方案:

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相同。

但是,我认为这是一个味道的问题,但。

如果只有两个谓词,我会拿出以下内容:

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

另外,如上所述,如果t这里有两个以上的谓词,最好把所有的谓词放在特定的函数中。 使用all可以使条件块更加杂乱(因为在这种情况下所有谓词都以逗号分隔)。