任何()函数的相反是什么?

81

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

8
你的问题已经被Jack Aidley正确回答了。你可以查看https://en.wikipedia.org/wiki/De_Morgan's_laws来了解其背后的理论。 - VPfB
2
根据你的问题,JackAidley和deceze的回答都可能有所帮助。请注意,“任何元素为假”并不等同于“没有元素为真”-它们对于空数组有不同的答案。 - Kos
1
请注意,all 在空可迭代对象上返回 True。当然会这样做,你还有其他期望吗?参考维基百科 - Bergi
2
@Bergi 不是的,我只是想向一些 Flash 程序员提醒这个有趣的特性。我的用词有什么问题吗? - Ekeyme Mo
@EkeymeMo:不知道,听起来像是一个警告,好像是要避免某些事情。或者这只是我的想法。 - Bergi
我在几年前的Python邮件列表上建议引入none(...)来达到这个目的,但是这个建议被驳回了,主要是因为它与None太相似了。 - ssc
4个回答

141

还有一个all函数,它与您想要的相反,如果所有值都为True,则返回True,如果任何值为False,则返回False。因此,您只需执行以下操作即可:

not all(l)

24
如果可迭代对象为空,不确定 OP 希望什么,但值得注意的是,在空的可迭代对象上 all 返回 True。 - Lafexlos
1
@Lafexlos 很好的观点,考虑终点总是值得的。我猜[]False是正确答案;这段代码给出了答案,但OP必须指定。 - Jack Aidley
7
对于 all(...),你总是可以在参数列表中添加 True 而不改变输出。 True 是一个“中性元素”(就像加法的0,乘法的1一样是中性元素)。这就是为什么空的 all() 返回 True。对于 any(),中性元素是 False - VPfB
1
@Fermiparadox:进行了一些快速的计时,这种方法比使用 any 的方法要快得多,正如你所期望的那样,因为它是内置的。然而,Deceze的方法更加普适。 - Jack Aidley
16
数理逻辑的一点知识可以在长远来看节省大量时间:∃x: ¬x 等同于 ¬(∀x: x)。详见此处 - BlueRaja - Danny Pflughoeft
显示剩余4条评论

54

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

编写一个生成器表达式,测试您自定义的条件。您不必局限于默认的真值检测

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
避免使用==运算符来与布尔值进行比较。只需使用裸值,例如if value: ...。但是,如果您一定要检查一个对象是否为布尔值而不是真值,请使用is。否则会得到意外的结果——例如,1 == True为真,但2 == True为假。 - Dunes
4
这比“not all(l)”慢得多。 - dawg
1
@Barmar all 也会在遇到 False 时短路;我认为硬编码的 C 风格检查 False 比在生成器中使用 Python 的 not i 更简单更快。 - deceze
显示剩余2条评论

16

好的,any 的实现与 等价 于:

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

因此,只需将条件从if element更改为if not element

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

当然,这种方法并没有像其他答案中使用的内置函数anyall那样利用速度,但它是一种好的可读性替代方案。


5
“当然啊”,我从未提出过相反的说法。我只是提供了一种替代方法。请记住,“any”和“all”通常对新用户来说很难理解,查看它们的粗略实现通常会有所帮助。 - Dimitris Fasarakis Hilliard

11

你可以做:

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

请注意,在Python 3中,map是一个生成器。对于Python 2,您可能需要使用imap


我的错:经过计时,我提供的方法无疑是最慢的

最快的方法是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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接