我正在通过脚本流式传输一个非常大的集合,目前正在使用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调用似乎很难实现(并且可能不是最佳选择)。也许我可以构造一个调用所有谓词的函数,但是如何尽可能简洁地(尽管仍然可读)编写它?
答案 0 :(得分: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))
您可以同时为或 -ing函数实现类似的disjoin
函数:
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函数操作函数,可以构造任何逻辑运算:)
答案 1 :(得分: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
相同。
但是,我认为这是一个品味问题。
答案 2 :(得分:0)
如果只有两个谓词,我会想出以下内容:
ifilter(lambda x: x in accept_list and x not in block_list, read_records(filename))
另外,如上所述,如果有两个以上的谓词,最好将所有谓词放在特定的函数中。
使用all
会使条件块变得更加混乱(因为在这种情况下所有谓词都用逗号分隔)。