简洁的方式来调用与蟒蛇多个谓词
问题描述:
我流一个非常大的集合通过一个脚本,我目前在一个简单的通话使用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
并使用all
或any
,但这是不可取的,因为使用它们将需要评估参数上的每个谓词。这里介绍的解决方案是令人满意的短路。
而且,只是为了好玩,让我们实现一个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
可以使条件块更加杂乱(因为在这种情况下所有谓词都以逗号分隔)。