与any()函数相反


72

Python的内置功能any(iterable)可以帮助快速检查是否有bool(element)True一个迭代的类型。

>>> l = [None, False, 0]
>>> any(l)
False
>>> l = [None, 1, 0]
>>> any(l)
True

但是Python中是否有一种优雅的方式或函数可以实现与之相反的效果any(iterable)?也就是说,如果有bool(element) is False则返回True,如以下示例所示:

>>> l = [True, False, True]
>>> any_false(l)
>>> True

6
杰克·艾德利已经正确回答了您的问题。您可能需要查看en.wikipedia.org/wiki/De_Morgan's_laws背后的理论。
VPfB

2
JackAidley和deceze的答案都可以有所帮助,具体取决于您的问题。请注意,“任何元素都是虚假的”与“没有元素是真实的”是不同的-它们对空数组有不同的答案。
科斯

1
注意会all返回True空的可迭代”-当然可以。您是否期望否则?
Bergi '16

1
@Bergi Nope,我只想注意到一些Flash使用者这个有趣的功能。我的话有什么问题吗?
Ekeyme Mo

@EkeymeMo:Dunno,听起来像是警告,就像是要避免的东西。也许只是我。
Bergi

Answers:


122

也有all它确实你想要什么相反的功能,它返回True如果都是TrueFalse如果有任何False。因此,您可以执行以下操作:

not all(l)

22
不确定OP想要什么,如果iterable为空,但值得注意的是,如果为空,则all返回True。
Lafexlos

1
@Lafexlos好点,总是值得考虑终点。我猜想,False对于[]是正确的答案; 该代码给出的内容,但OP必须指定。
杰克·艾德利

6
因为all(...)您始终可以添加True到参数列表而无需更改输出。True是“中性元素”(就像0表示加法,1表示乘法是中性元素)。这就是为什么空all()返回True。对于any()中性元素是False
VPfB

1
@Fermiparadox:做一些快速的计时比any您期望的方法快得多,因为它是内置的。但是,Deceze的方法更普遍。
杰克·艾德利

15
+1从长远来看,对数学逻辑的一点了解可以节省大量时间:∃x: ¬x等同于¬(∀x: x)。看到这里
BlueRaja-Danny Pflughoeft

48

编写一个生成器表达式以测试您的自定义条件。您不仅限于默认的真实性测试:

any(not i for i in l)

2
是的,可能any(bool(i) == False for i in l)更好。对?None == FalseFalse,但我不想要那样。bool(None) == FalseTrue
Ekeyme Mo

2
在那种情况下not i for i in l可能是最好的。
deceze

4
@EkeymeMo避免==用于与布尔值进行比较。只需使用裸值即可。if value: ...。但是,如果您绝对必须检查对象是否为布尔值而不是真实值,请使用is。否则,您会得到意想不到的结果-例如。1 == True是正确的,但是2 == True错误的。
沙丘

4
这明显慢于not all(l)
dawg'8

1
@Barmarall会在遇到短路时立即短路False;我认为在生成器中使用硬编码的C样式进行检查False比在Pythonnot i中更简单……
deceze

16

那么,执行any等价于:

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

因此,只需将条件从切换if elementif not element

def reverse_any(iterable):
    for element in iterable:
        if not element:
            return True
    return False

是的,当然,这并不能充分利用内建的速度anyall像其他的答案做的,但它是一个不错的替代可读性。


5
@JackAidley当然是,否则我从不做任何断言。我刚刚添加了一个替代方案。请记住,any并且all通常会使新用户迷惑不解,查看他们的粗略实施通常会有所帮助。
Dimitris Fasarakis Hilliard'8

9

你可以做:

>>> l = [True, False, True]
>>> False in map(bool, l)
True

回想一下,map在Python 3中是生成器。对于Python 2,您可能要使用imap


Mea Culpa:确定这些时间之后,我提供的方法是最慢的

最快的就是not all(l)或者not next(filterfalse(bool, it), True)只是一个愚蠢的itertools变体。使用Jack Aidleys解决方案

时间码:

from itertools import filterfalse

def af1(it):
    return not all(it)

def af2(it):
    return any(not i for i in it)   

def af3(iterable):
    for element in iterable:
        if not element:
            return True
    return False    

def af4(it):
    return False in map(bool, it)   

def af5(it):
    return not next(filterfalse(bool, it), True)    

if __name__=='__main__':
    import timeit   
    for i, l in enumerate([[True]*1000+[False]+[True]*999, # False in the middle
                           [False]*2000, # all False
                            [True]*2000], # all True
                            start=1): 
        print("case:", i)
        for f in (af1, af2, af3, af4, af5):
            print("   ",f.__name__, timeit.timeit("f(l)", setup="from __main__ import f, l", number=100000), f(l) )

结果:

case: 1
    af1 0.45357259700540453 True
    af2 4.538436588976765 True
    af3 1.2491040650056675 True
    af4 8.935278153978288 True
    af5 0.4685744970047381 True
case: 2
    af1 0.016299808979965746 True
    af2 0.04787631600629538 True
    af3 0.015038023004308343 True
    af4 0.03326922300038859 True
    af5 0.029870904982089996 True
case: 3
    af1 0.8545824179891497 False
    af2 8.786235476000002 False
    af3 2.448748088994762 False
    af4 17.90895140200155 False
    af5 0.9152941330103204 False
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.