How does python interpret "True != True != True"? [duplicate] - python

As expected, 1 is not contained by the empty tuple
>>> 1 in ()
False
but the False value returned is not equal to False
>>> 1 in () == False
False
Looking at it another way, the in operator returns a bool which is neither True nor False:
>>> type(1 in ())
<type 'bool'>
>>> 1 in () == True, 1 in () == False
(False, False)
However, normal behaviour resumes if the original expression is parenthesized
>>> (1 in ()) == False
True
or its value is stored in a variable
>>> value = 1 in ()
>>> value == False
True
This behaviour is observed in both Python 2 and Python 3.
Can you explain what is going on?

You are running into comparison operator chaining; 1 in () == False does not mean (1 in ()) == False.
Rather, comparisons are chained and the expression really means:
(1 in ()) and (() == False)
Because (1 in ()) is already false, the second half of the chained expression is ignored altogether (since False and something_else returns False whatever the value of something_else would be).
See the comparisons expressions documentation:
Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).
For the record, <, >, ==, >=, <=, !=, is, is not, in and not in are all comparison operators (as is the deprecated <>).
In general, don't compare against booleans; just test the expression itself. If you have to test against a boolean literal, at least use parenthesis and the is operator, True and False are singletons, just like None:
>>> (1 in ()) is False
True
This gets more confusing still when integers are involved. The Python bool type is a subclass of int1. As such, False == 0 is true, as is True == 1. You therefor can conceivably create chained operations that almost look sane:
3 > 1 == True
is true because 3 > 1 and 1 == True are both true. But the expression:
3 > 2 == True
is false, because 2 == True is false.
1 bool is a subclass of int for historic reasons; Python didn't always have a bool type and overloaded integers with boolean meaning just like C does. Making bool a subclass kept older code working.

Related

Order of operation evaluation in condition in Python

If I have something like a = [1,2,3] and I write a statement like 1 in a == True, that appears to evaluate to false.
However, if I write (1 in a) == True, that evaluates to true.
I am slightly confused about how Python evaluates the first statement to reach false in the end.
Both == and in are considered comparison operators, meaning that operator chaining comes into effect:
Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).
This chaining is what allows you to write:
if 0 <= x < 20: # meaning: if x >= 0 and x < 20:
Hence the expression 1 in a == True is chained as 1 in a and a == True and, since the right side of that and evaluates to false, the entire expression is false.
This chaining does not occur when you "isolate" part of the expression with parentheses, which is why (1 in a) == True acts as you expect.
Having explained that, comparing a boolean value with True (or False for that matter) is not really something you should be doing anyway, since that leads to logically infinite scenarios like:
if (((a == 7) == True) != False) == True # 'a == 7' already a boolean.
Far better just to use one of:
if expression # if comparing with True
if not expression # if comparing with False

Why is `True is False == False`, False in Python? [duplicate]

This question already has an answer here:
Why does (1 in [1,0] == True) evaluate to False?
(1 answer)
Closed 7 years ago.
Why is it that these statements work as expected when brackets are used:
>>> (True is False) == False
True
>>> True is (False == False)
True
But it returns False when there are no brackets?
>>> True is False == False
False
Based on python documentation about operator precedence :
Note that comparisons, membership tests, and identity tests, all have the same precedence and have a left-to-right chaining feature as described in the Comparisons section.
So actually you have a chained statement like following :
>>> (True is False) and (False==False)
False
You can assume that the central object will be shared between 2 operations and other objects (False in this case).
And note that its also true for all Comparisons, including membership tests and identity tests operations which are following operands :
in, not in, is, is not, <, <=, >, >=, !=, ==
Example :
>>> 1 in [1,2] == True
False
Python has a unique transitive property when it comes to the comparison operators. It will be easier to see in a simpler case.
if 1 < x < 2:
# Do something
This does what it looks like. It checks if 1 < x and if x < 2. The same thing is happening in your non-parenthesized code.
>>> True is False == False
False
It is checking whether True is False and False == False, only one of which is true.
This is a double inequality which gets expanded as (True is False) and (False == False). See for instance What is the operator precedence when writing a double inequality in Python (explicitly in the code, and how can this be overridden for arrays?)
Python interprets multiple (in)equalities the way you would expect in Math:
In Math a = b = c mean all a = b, b = c and a = c.
So True is False == False means True == False and False == False and True == False, which is False.
For boolean constants, is is equivalent to ==.
Python performs chaining if it encounters operators of same precedence when evaluating an expression.
comparisons, including tests, which all have the same precedence
chain from left to right
The below mentioned operators have the same precedence.
in, not in, is, is not, <, <=, >, >=, <>, !=, ==
So, when Python tries to evaluate the expression True is False == False, it encounters the operators is and == which have the same precedence, so it performs chaining from left to right.
So, the expression True is False == False is actually evaluated as:
(True is False) and (False == False)
giving False as the output.

bool and int types in boolean contexts

I have this code in a boolean context:
True and False or 2
Output: 2
The type check for this expression resulted in int.
Next, I modified the code to:
True and False or True
Output : True
And the type check for this expression resulted in bool
Why is the output in the 1st code 2?
Shouldn't the expression evaluate to a boolean value ?
If not so, Why?
All you need to know here is the definition of OR operand.Based on python documentation :
The expression x or y first evaluates x; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned.
So since the precedence of or is lower than and your expression evaluated as following :
(True and False) or 2
Which is equal to following :
False or 2
Thus based on preceding documentation the result would be the value of right object which is 2.
In Python, when using 'and' and 'or', the expression evaluates using the objects involved, instead of using Booleans as in many other languages.
So:
1 and 2 will evaluate to 2
1 or 2 will evaluate to 1 (short-circuit)
1 and "hello" will evaluate to "hello"
... and so on
If you want the Boolean, just surround the whole expression with bool(..)
Further reading:
http://www.diveintopython.net/power_of_introspection/and_or.html
https://docs.python.org/2/reference/expressions.html#boolean-operations
When you said True and False it is evaluate to False.
Then you have False or 2 which will evaluate to 2
Now True and False or True will evaluate to True but the last True in your expression. This is due to operator precedence
>>> True and False
False
>>> False or 2
2
>>>
The output is 2 not True because True and False or 2 is like
var = (True and False)
if var:
print(var)
else:
print(2)
which yields
2
because True and False will always evaluate to False
I think you are clear with the operator precedence between and and or.According to Python documentation, the object is returned.
>>> 1 and 2
will return 2 according to the shorcut evaluation.
and so on.

What should be simple expression (containing less_than, is, and) result? Why? [duplicate]

As expected, 1 is not contained by the empty tuple
>>> 1 in ()
False
but the False value returned is not equal to False
>>> 1 in () == False
False
Looking at it another way, the in operator returns a bool which is neither True nor False:
>>> type(1 in ())
<type 'bool'>
>>> 1 in () == True, 1 in () == False
(False, False)
However, normal behaviour resumes if the original expression is parenthesized
>>> (1 in ()) == False
True
or its value is stored in a variable
>>> value = 1 in ()
>>> value == False
True
This behaviour is observed in both Python 2 and Python 3.
Can you explain what is going on?
You are running into comparison operator chaining; 1 in () == False does not mean (1 in ()) == False.
Rather, comparisons are chained and the expression really means:
(1 in ()) and (() == False)
Because (1 in ()) is already false, the second half of the chained expression is ignored altogether (since False and something_else returns False whatever the value of something_else would be).
See the comparisons expressions documentation:
Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).
For the record, <, >, ==, >=, <=, !=, is, is not, in and not in are all comparison operators (as is the deprecated <>).
In general, don't compare against booleans; just test the expression itself. If you have to test against a boolean literal, at least use parenthesis and the is operator, True and False are singletons, just like None:
>>> (1 in ()) is False
True
This gets more confusing still when integers are involved. The Python bool type is a subclass of int1. As such, False == 0 is true, as is True == 1. You therefor can conceivably create chained operations that almost look sane:
3 > 1 == True
is true because 3 > 1 and 1 == True are both true. But the expression:
3 > 2 == True
is false, because 2 == True is false.
1 bool is a subclass of int for historic reasons; Python didn't always have a bool type and overloaded integers with boolean meaning just like C does. Making bool a subclass kept older code working.

Python's in (__contains__) operator returns a bool whose value is neither True nor False

As expected, 1 is not contained by the empty tuple
>>> 1 in ()
False
but the False value returned is not equal to False
>>> 1 in () == False
False
Looking at it another way, the in operator returns a bool which is neither True nor False:
>>> type(1 in ())
<type 'bool'>
>>> 1 in () == True, 1 in () == False
(False, False)
However, normal behaviour resumes if the original expression is parenthesized
>>> (1 in ()) == False
True
or its value is stored in a variable
>>> value = 1 in ()
>>> value == False
True
This behaviour is observed in both Python 2 and Python 3.
Can you explain what is going on?
You are running into comparison operator chaining; 1 in () == False does not mean (1 in ()) == False.
Rather, comparisons are chained and the expression really means:
(1 in ()) and (() == False)
Because (1 in ()) is already false, the second half of the chained expression is ignored altogether (since False and something_else returns False whatever the value of something_else would be).
See the comparisons expressions documentation:
Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).
For the record, <, >, ==, >=, <=, !=, is, is not, in and not in are all comparison operators (as is the deprecated <>).
In general, don't compare against booleans; just test the expression itself. If you have to test against a boolean literal, at least use parenthesis and the is operator, True and False are singletons, just like None:
>>> (1 in ()) is False
True
This gets more confusing still when integers are involved. The Python bool type is a subclass of int1. As such, False == 0 is true, as is True == 1. You therefor can conceivably create chained operations that almost look sane:
3 > 1 == True
is true because 3 > 1 and 1 == True are both true. But the expression:
3 > 2 == True
is false, because 2 == True is false.
1 bool is a subclass of int for historic reasons; Python didn't always have a bool type and overloaded integers with boolean meaning just like C does. Making bool a subclass kept older code working.

Categories