Why Does "A == X or Y or Z" Always Evaluate to True

Why does a == x or y or z always evaluate to True? How can I compare a to all of those?

In many cases, Python looks and behaves like natural English, but this is one case where that abstraction fails. People can use context clues to determine that "Jon" and "Inbar" are objects joined to the verb "equals", but the Python interpreter is more literal minded.

if name == "Kevin" or "Jon" or "Inbar":

is logically equivalent to:

if (name == "Kevin") or ("Jon") or ("Inbar"):

Which, for user Bob, is equivalent to:

if (False) or ("Jon") or ("Inbar"):

The or operator chooses the first argument with a positive truth value:

if "Jon":

And since "Jon" has a positive truth value, the if block executes. That is what causes "Access granted" to be printed regardless of the name given.

All of this reasoning also applies to the expression if "Kevin" or "Jon" or "Inbar" == name. the first value, "Kevin", is true, so the if block executes.


There are two common ways to properly construct this conditional.

  1. Use multiple == operators to explicitly check against each value:

    if name == "Kevin" or name == "Jon" or name == "Inbar":
  2. Compose a collection of valid values (a set, a list or a tuple for example), and use the in operator to test for membership:

    if name in {"Kevin", "Jon", "Inbar"}:

In general of the two the second should be preferred as it's easier to read and also faster:

>>> import timeit
>>> timeit.timeit('name == "Kevin" or name == "Jon" or name == "Inbar"',
setup="name='Inbar'")
0.4247764749999945
>>> timeit.timeit('name in {"Kevin", "Jon", "Inbar"}', setup="name='Inbar'")
0.18493307199999265

For those who may want proof that if a == b or c or d or e: ... is indeed parsed like this. The built-in ast module provides an answer:

>>> import ast
>>> ast.parse("a == b or c or d or e", "<string>", "eval")
<ast.Expression object at 0x7f929c898220>
>>> print(ast.dump(_, indent=4))
Expression(
body=BoolOp(
op=Or(),
values=[
Compare(
left=Name(id='a', ctx=Load()),
ops=[
Eq()],
comparators=[
Name(id='b', ctx=Load())]),
Name(id='c', ctx=Load()),
Name(id='d', ctx=Load()),
Name(id='e', ctx=Load())]))

As one can see, it's the boolean operator or applied to four sub-expressions: comparison a == b; and simple expressions c, d, and e.

Why is `!!(a||!a)` always true?

First off, !! expression cancels out: it’s the same as expression, because the negation of a negation is the original value.

So we’re left with a || ! a, which is a disjunction. So the result is true if at least one of the sub-expressions a or !a is true.

And lastly, a is true if a is true (duh). And ! a is true if a is false. Thus, regardless of the value of a, the overall expression is true.

Can someone explain why print(red == blue or 3 = 3) returns True

When you use the Boolean Operator or, only one of the conditions declared has to be true in order for it to return true. 3>=3 is true, so the whole expression is true.

If statement not returning expected result

Your problem is with if score == 2 or 3.

You can re-write that as (score == 2) or (3) which resolves to False or True or True or True, which is always True.

This is a bit quirky of Python. bool(any_object) returns True if the object is not None. Try bool(3) and see that you get True from it.

What you meant to do is if (score == 2) or (score == 3) or if score in [2, 3], either of those would work.

Why is my or statement not working as I want?

Instead of if repeat == "No" or "no", use:

if repeat == "No" or repeat == "no"

Or even:

if repeat in ("No", "no")


Related Topics



Leave a reply



Submit