0

I'm learning the language python. And although it is very simple indeed, I got some unexpected results using logic operators both in IDLE and in python.

I made a simple test in IDLE like this:

(2 or 10) in range(1,6)

And my response was True. So far so good. However, if I do this:

(10 or 2) in range(1,6)

My response is False. Even though "2" is clearly inside the range(1,6).

I made the same test in PyCharm and here are my responces:

if (2 or 10) in range(1,6):
    print("True")
else:
    print("False")

Result: True

if (10 or 2) in range(1,6):
    print("True")
else:
    print("False")

Result: False

if 2 or 10 in range(1,6):
    print("True")
else:
    print("False")

Result: True

if 10 or 2 in range(1,6):
    print("True")
else:
    print("False")

Result: True

I would like to know the logic behind it please.

martineau
  • 119,623
  • 25
  • 170
  • 301
andseg
  • 658
  • 1
  • 9
  • 26
  • 1
    First of all `or` in Python is **not** a logical operator. Second, it should be `10 in range(1,6) or 2 in range(1,6)`... Otherwise you have written `(10 or 2) in range(1,6))`... which resolves to `10 in range(1,6)`... – Willem Van Onsem Mar 21 '17 at 19:42
  • Enlight me please. Show documents for me to read, proof, evidence, something. – andseg Mar 21 '17 at 19:45
  • http://www.diveintopython.net/power_of_introspection/and_or.html – Willem Van Onsem Mar 21 '17 at 19:45
  • @WillemVanOnsem thanks – andseg Mar 21 '17 at 19:47
  • `or` shortcircuits. `(10 or 2)` evaluates to `10`, `(10 or 2)` evaluates to `2`. It also has higher precedence than `in`, so `if 2 or 10 in range(1,6)` is equivalent to `if 2 in range(1,6)`, while `if 10 or 2 in range(1, 6)` is equivalent to `if 10 in range(1,6)`. – Peter DeGlopper Mar 21 '17 at 19:47
  • I think I got it. However, how do I rewrie the code using the boolean operator "or" to check if 10 || 2 is in range? – andseg Mar 21 '17 at 19:52
  • 1
    @andseg: try using the [`any`](https://docs.python.org/3.5/library/functions.html#any) function: `print(any(x in range(1,6) for x in [10,2]))`. There's also an `all` function that behaves like you were expecting for logical AND. – Matthew Cole Mar 21 '17 at 19:54

1 Answers1

3

OR returns the first TRUE value it encounters.

That is:

>>> (2 or 10) 
# returns 2
>>> (10 or 2)
# returns 10

Update

To address OP's comment below:

There are truthy values which evaluate to True and there are falsey values which evaluate to False. For example, 0 is a falsey value. Rest of the integers are truthy values. Therefore, 10 is also a truthy value.

If you do:

>>> if 10: # since 10 is truthy, this statement will execute.
        print("Okay!")
    else:
        print("Not okay!")

# prints "Okay!"

Moving on, 10 or 2 in range(1, 6) evaluates to 10 or (2 in range(1, 6)).

 10     or     (2 in range(1, 6))
\__/           \________________/
True               True

# Returns 10 because it's a truthy value. 
# OR operator only evaluates until it finds a True value.

Let's see another example:

 0      or    10
\_/          \__/
False        True

# Returns 10 because 0 is a falsey value, so the 
# OR operator continues evaluating the rest of the expression

Finally, let's see the if expression:

 >>> if 10 or 2 in range(1, 6):
        print("True")
     else:
        print("False")
 # prints "True"

It prints True because 10 or 2 in range(1, 6) returns 10 and as we saw above, if 10 evaluates to True, hence, the if block is executed.


Additionally:

The correct expression will be this:

>>> 10 in range(1, 6) or 2 in range(1, 6)
# returns True

This expression will return True because even though 10 is not in the given range, but 2 is.

10 in range(1, 6)   or   2 in range(1, 6)
\_______________/        \______________/ 
     False                     True

# Returns True because OR will keep on evaluating
# until it finds a True value

But if you want to check if 10 and 2 both are in the range, you'll have to use the AND operator:

>>> 10 in range(1, 6) and 2 in range(1, 6)
# returns False
xyres
  • 20,487
  • 3
  • 56
  • 85
  • @andseg: since you asked for a reference in a comment to your question... here's where it's documented in the [Python 3.5 documentation](https://docs.python.org/3.5/reference/expressions.html#boolean-operations) – Matthew Cole Mar 21 '17 at 19:48
  • using `(10 or 2)` returns 10.... and 10 is not in range(1,6) so it returns false. right? but what about using `10 or 2 in range(1,6)`? using idle it returns 10 as well, but in PyCharm the "if" is taken. Why? – andseg Mar 21 '17 at 20:08
  • @andseg I don't understand what you mean by *"... but in PyCharm the "if" is taken"...*. Can you please elaborate on that? – xyres Mar 21 '17 at 20:13
  • using IDLE, the line `10 or 2 in range(1,6)`returns 10. However, using PyCharm, the line `if 10 or 2 in range(1,6):` returns true.... which print the message "True". Why am I getting a true? – andseg Mar 21 '17 at 20:20
  • @andseg I've updated the answer and tried my best to explain. Have a look. – xyres Mar 21 '17 at 21:01