Python中的any()函数带callback

Python标准库定义了一个any()函数

如果迭代的任何元素为真,则返回True。 如果迭代是空的,则返回False。

它只检查元素是否评估为True 。 我希望它能够指定一个callback来判断一个元素是否符合这个法案:

 any([1, 2, 'joe'], lambda e: isinstance(e, int) and e > 0) 

怎么样:

 >>> any(isinstance(e, int) and e > 0 for e in [1,2,'joe']) True 

它也适用于all()当然:

 >>> all(isinstance(e, int) and e > 0 for e in [1,2,'joe']) False 

当任何条件为真时, 任何函数都返回True。

 >>> any(isinstance(e, int) and e > 0 for e in [0 ,0, 1]) True # Returns True because 1 is greater than 0. >>> any(isinstance(e, int) and e > 0 for e in [0 ,0, 0]) False # Returns False because not a single condition is True. 

实际上, 任何函数的概念都是从Lisp引入的,或者你可以从函数编程的angular度来说。 还有另外一个function是完全相反的

 >>> all(isinstance(e, int) and e > 0 for e in [1, 33, 22]) True # Returns True when all the condition satisfies. >>> all(isinstance(e, int) and e > 0 for e in [1, 0, 1]) False # Returns False when a single condition fails. 

这两个function在正确使用时非常酷。

哟应该使用“生成器expression式” – 也就是说,一个语言结构,可以消耗迭代器,然后在一行上应用filter和expression式:

例如(i ** 2 for i in xrange(10))是前10个自然数(0到9)的平方的生成器,

它们还允许“if”子句过滤“for”子句中的itens,因此对于您的示例,您可以使用:

 any (e for e in [1, 2, 'joe'] if isinstance(e, int) and e > 0) 

稍微改善了Antoine P的答案

 >>> any(type(e) is int for e in [1,2,'joe']) True 

对于all()

 >>> all(type(e) is int for e in [1,2,'joe']) False 

虽然其他人给出了很好的Pythonic答案(我只是在大多数情况下使用公认的答案),但我只想指出,如果你真的喜欢,自己做一个实用函数是很容易的:

 def any_lambda(iterable, function): return any(function(i) for i in iterable) In [1]: any_lambda([1, 2, 'joe'], lambda e: isinstance(e, int) and e > 0 Out[1]: True In [2]: any_lambda([-1, '2', 'joe'], lambda e: isinstance(e, int) and e > 0) Out[2]: False 

我想我至less应该首先用函数参数来定义它,因为它更接近现有的内置函数,比如map()和filter():

 def any_lambda(function, iterable): return any(function(i) for i in iterable) 

filter可以工作,再加上它会返回匹配的元素

 >>> filter(lambda e: isinstance(e, int) and e > 0, [1,2,'joe']) [1, 2] 

如果你真的想保留你的lambda符号,你可以使用anymap的组合:

 any(map(lambda e: isinstance(e, int) and e > 0, [1, 2, 'joe'])) 

但是最好使用一个生成器expression式,因为它不会构build整个列表两次。

如果你真的想在任何()中内联一个lambda,你可以这样做:

 >>> any((lambda: isinstance(e, int))() for e in [1,2,'joe']) True >>> any((lambda: isinstance(e, int))() for e in ['joe']) False 

你只需要包装未命名的lambda,并确保每次传递都会调用()

这样做的好处是,当你打到第一个int的时候,你仍然可以利用短路的评估