Why does checking a variable against multiple values with `OR` only check the first value? [duplicate]

Solution 1:

("Jesse" or "jesse")

The above expression tests whether or not "Jesse" evaluates to True. If it does, then the expression will return it; otherwise, it will return "jesse". The expression is equivalent to writing:

"Jesse" if "Jesse" else "jesse"

Because "Jesse" is a non-empty string though, it will always evaluate to True and thus be returned:

>>> bool("Jesse")  # Non-empty strings evaluate to True in Python
True
>>> bool("")  # Empty strings evaluate to False
False
>>>
>>> ("Jesse" or "jesse")
'Jesse'
>>> ("" or "jesse")
'jesse'
>>>

This means that the expression:

name == ("Jesse" or "jesse")

is basically equivalent to writing this:

name == "Jesse"

In order to fix your problem, you can use the in operator:

# Test whether the value of name can be found in the tuple ("Jesse", "jesse")
if name in ("Jesse", "jesse"):

Or, you can lowercase the value of name with str.lower and then compare it to "jesse" directly:

# This will also handle inputs such as "JeSSe", "jESSE", "JESSE", etc.
if name.lower() == "jesse":

Solution 2:

if name in ("Jesse", "jesse"):

would be the correct way to do it.

Although, if you want to use or, the statement would be

if name == 'Jesse' or name == 'jesse':

>>> ("Jesse" or "jesse")
'Jesse'

evaluates to 'Jesse', so you're essentially not testing for 'jesse' when you do if name == ("Jesse" or "jesse"), since it only tests for equality to 'Jesse' and does not test for 'jesse', as you observed.

Solution 3:

If you want case-insensitive comparison, use lower or upper:

if name.lower() == "jesse":

Solution 4:

The or operator returns the first operand if it is true, otherwise the second operand. So in your case your test is equivalent to if name == "Jesse".

The correct application of or would be:

if (name == "Jesse") or (name == "jesse"):