81

The Python built-in function any(iterable) can help to quickly check if any bool(element) is True in a iterable type.

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

But is there an elegant way or function in Python that could achieve the opposite effect of any(iterable)? That is, if any bool(element) is False then return True, like the following example:

>>> l = [True, False, True]
>>> any_false(l)
>>> True
Cœur
  • 37,241
  • 25
  • 195
  • 267
Ekeyme Mo
  • 1,247
  • 1
  • 9
  • 11
  • 8
    Your question was correctly answered already by jack Aidley. You may want to check https://en.wikipedia.org/wiki/De_Morgan's_laws for the theory behind it. – VPfB Aug 10 '16 at 12:04
  • 2
    Both JackAidley's and deceze's answer can be helpful depending on your problem. Note that "any element is falsy" isn't the same as "no element is truthy" - they have different answers for the empty array. – Kos Aug 10 '16 at 13:46
  • 1
    "*notice that `all` returns `True` on empty iterable*" - [of course it does](https://en.wikipedia.org/wiki/Vacuous_truth). Did you expect otherwise? – Bergi Aug 11 '16 at 11:32
  • 2
    @Bergi Nope, I just want to notice some flash people this interesting feature. Anything wrong with my word? – Ekeyme Mo Aug 11 '16 at 12:29
  • @EkeymeMo: Dunno, sounded like a warning, as like for something to avoid. Or maybe it's just me. – Bergi Aug 11 '16 at 12:39
  • I suggested on the Python mailing list a couple of years back introducing `none(...)` for that very purpose, but the suggestion was dismissed, mostly due to its resemblance to `None`. – ssc Aug 11 '16 at 17:49

4 Answers4

141

There is also the all function which does the opposite of what you want, it returns True if all are True and False if any are False. Therefore you can just do:

not all(l)
Jack Aidley
  • 19,439
  • 7
  • 43
  • 70
  • 24
    Not sure what OP wants if iterable is empty but it's worth noting, `all` returns True on empty iterable. – Lafexlos Aug 10 '16 at 09:30
  • 1
    @Lafexlos Good point, it's always worth considering the end points. I would guess that `False` for `[]` is the correct answer; which this code give but the OP would have to specify. – Jack Aidley Aug 10 '16 at 11:07
  • 6
    For `all(...)` you can always add `True` to the argument list without changing the output. `True` is a "neutral element" (just like 0 for addition, 1 for multiplication are neutral elements). That's why empty `all()` returns `True`. For `any()` the neutral element is `False`. – VPfB Aug 10 '16 at 12:14
  • 1
    @Fermiparadox: Doing some quick timings this is much faster than the `any` approach as you'd expect since it's all built-in. Deceze's approach is more generally applicable, however. – Jack Aidley Aug 10 '16 at 13:31
  • 16
    +1 A little knowledge of mathematical logic can save a lot of time in the long run: `∃x: ¬x` is equivalent to `¬(∀x: x)`. See [here](https://en.wikipedia.org/wiki/Existential_quantification#Negation) – BlueRaja - Danny Pflughoeft Aug 10 '16 at 16:22
  • @Lafexlos, yes, `all` returns True on an empty set because that's how the underlying math works. – Arturo Torres Sánchez Aug 11 '16 at 16:42
  • 1
    This doesn't short circuit though, if that is the desired behavior. – Shane Hsu Aug 16 '16 at 18:54
  • @ShaneHsu: Short circuiting may not be faster than native C code of `all` – dawg Aug 16 '16 at 21:55
  • 1
    @ShaneHsu: What do you mean by "doesn't short circuit"? The `all` call terminates on the first `False` found and is thus much faster for a call with `False` at the start and slower for all `True` - I would describe that as short circuiting. – Jack Aidley Aug 17 '16 at 15:38
54

Write a generator expression which tests your custom condition. You're not bound to only the default truthiness test:

any(not i for i in l)
deceze
  • 510,633
  • 85
  • 743
  • 889
  • 2
    Yeah, might be `any(bool(i) == False for i in l)` is better. Right? `None == False` is `False`, but I don't want that. `bool(None) == False` is `True` – Ekeyme Mo Aug 10 '16 at 09:27
  • 2
    In that case `not i for i in l` would probably be best. – deceze Aug 10 '16 at 09:28
  • 4
    @EkeymeMo Avoid using `==` to compare against booleans. Just use the bare value eg. `if value: ...`. However, if you absolutely must check if an object is a boolean rather than a truthful value, use `is`. Otherwise you can get unexpected results -- eg. `1 == True` is true, but `2 == True` is false. – Dunes Aug 10 '16 at 09:42
  • 4
    This is significantly slower than `not all(l)` – dawg Aug 11 '16 at 01:02
  • @dawg I'm surprised, because this allows short-circuiting, so it can return as soon as a `false` element is found. – Barmar Aug 16 '16 at 21:21
  • @Barmar: that was my instinct as well, but the timing code is in my post. I suppose that C native code of `all` beats short circuiting of `any` in this case. – dawg Aug 16 '16 at 21:54
  • 1
    @Barmar `all` will short-circuit as well as soon as it encounters `False`; I assume the hardcoded C style of checking for `False` is simple faster than a Python `not i` in a generator… – deceze Aug 17 '16 at 06:58
16

Well, the implementation of any is equivalent to:

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

So, just switch the condition from if element to if not element:

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

Yes, of course this doesn't leverage the speed of the built-ins any or all like the other answers do, but it's a nice readable alternative.

Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
  • 5
    @JackAidley *Of course it is*, I never made any assertions otherwise. I just added an alternative. Remember, `any` and `all` are generally mystifying to new users, looking at their rough implementation generally helps. – Dimitris Fasarakis Hilliard Aug 10 '16 at 11:13
11

You can do:

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

Recall that map in Python 3 is a generator. For Python 2, you probably want to use imap


Mea Culpa: After timing these, the method I offered is hands down the slowest

The fastest is not all(l) or not next(filterfalse(bool, it), True) which is just a silly itertools variant. Use Jack Aidleys solution.

Timing code:

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) )

Results:

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
Community
  • 1
  • 1
dawg
  • 98,345
  • 23
  • 131
  • 206