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符号,你可以使用any
和map
的组合:
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的时候,你仍然可以利用短路的评估