FCD
FCD

Reputation: 31

How to simplify multiple or conditions in an if statement?

So I wanted to write this:

if x % 2 == 0 or x % 3 == 0 or x % 5 == 0 or x % 7 == 0:

But this way:

if x % (2 or 3 or 5 or 7) == 0:

How should I write it in a proper way?

Upvotes: 3

Views: 4453

Answers (1)

Bakuriu
Bakuriu

Reputation: 101919

or is a boolean operator. It calls bool over the left argument and see if the result is True and if it is it returns the left argument, otherwise it returns the right argument, so you cannot do x % (1 or 2 or 3) because this evaluates to just x % 1 since 1 or 2 or 3 == 1:

>>> True or False
True
>>> False or True
True
>>> False or False
False
>>> 1 or False   # all numbers != 0 are "true"
1
>>> bool(1)
True
>>> 1 or 2 or 3   #(1 or 2) or 3 == 1 or 3 == 1
1

Whenever you have multiple conditions you can try to reduce them using any or all.

We have that any([a,b,c,d]) is equivalent to a or b or c or d while all([a,b,c,d]) is equivalent to a and b and c and d except that they always return True or False.

So for example:

if any(x%i == 0 for i in (2,3,5,7)):

Equivalently (since 0 if the only false number the == 0 is equivalent to not):

if any(not x%i for i in (2,3,5,7)):

Equivalently:

if not all(x%i for i in (2,3,5,7))

Keep in mind that (de Morgan law: not a or not b == not (a and b)):

any(not p for p in some_list) == not all(p for p in some_list)

Note that using a generator expression makes any and all short-circuit so not all conditions are evaluated. See the difference between:

>>> any(1/x for x in (1,0))
True
>>> 1 or 1/0
1

And:

>>> any([1/x for x in (1,0)])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
ZeroDivisionError: division by zero
>>> 1/0 or 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

In the last example the 1/0 is evaluated before calling any.

Upvotes: 8

Related Questions