Reputation: 31
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
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