i was testing the precedence of comparison and membership operator, as per Python documentation they are at same precedence. But it is showing strange results as follows,
If anyone can justify following code and the corresponding output..
print( ( True!= 12) in (12,14)) #output: False
print( True!= 12 in (12,14)) #output: True
print( True!= (12 in (12,14))) #output: False
From https://docs.python.org/3/reference/expressions.html:
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.
In the Comparisons section we find:
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).
So, your second line is equivalent to:
True != 12 and 12 in (12, 14)
which evaluates to True and True which evaluates to True.
Similarly curious constructions are:
>>> True == True in (True, False)
True
>>> True == False in (True, False)
False
>>> 2 == 2 in (2, 3)
True
>>> 1 == 1 in (2, 3)
False
>>> 1 != 2 in (2, 3)
True
>>> 2 != 1 in (2, 3)
False
>>> 2 in (2, 3) in [True, False]
False
First Case:
print((True != 12) in (12,14))
We can say that first we evaluate True != 12 condition which give us True, and then we are evaluating if True is in the tuple (12,14) and that's False.
Third Case:
print(True != (12 in (12,14)))
We can say that first we evaluate (12 in (12,14)) condition which give us True because 12 is in the tuple (12,14). Then we evaluate if True != True an that's False.
Second Case:
print( True != 12 in (12,14))
So here is the tricky one. Without the parentheses we don't have where to start evaluating the conditions. To explain this case, I'm gonna give you the next example: if you try the following code (which is pretty similar to the one that we are trying to figure out the result):
print(1 != 2 != 3) #output True
You are gonna get True and that's because 1 != 2 and 2 != 3. So as you may have already noticed, it's an implicit AND. The above code is equal to:
print(1 != 2 and 2 != 3) #output True
So if we take this logic to our case, we are evaluating this:
print( True != 12 and 12 in (12,14)) # => (True and True) #output True
Related
Does Python support short-circuiting in boolean expressions?
Yep, both and and or operators short-circuit -- see the docs.
Short-circuiting behavior in operator and, or:
Let's first define a useful function to determine if something is executed or not. A simple function that accepts an argument, prints a message and returns the input, unchanged.
>>> def fun(i):
... print "executed"
... return i
...
One can observe the Python's short-circuiting behavior of and, or operators in the following example:
>>> fun(1)
executed
1
>>> 1 or fun(1) # due to short-circuiting "executed" not printed
1
>>> 1 and fun(1) # fun(1) called and "executed" printed
executed
1
>>> 0 and fun(1) # due to short-circuiting "executed" not printed
0
Note: The following values are considered by the interpreter to mean false:
False None 0 "" () [] {}
Short-circuiting behavior in function: any(), all():
Python's any() and all() functions also support short-circuiting. As shown in the docs; they evaluate each element of a sequence in-order, until finding a result that allows an early exit in the evaluation. Consider examples below to understand both.
The function any() checks if any element is True. It stops executing as soon as a True is encountered and returns True.
>>> any(fun(i) for i in [1, 2, 3, 4]) # bool(1) = True
executed
True
>>> any(fun(i) for i in [0, 2, 3, 4])
executed # bool(0) = False
executed # bool(2) = True
True
>>> any(fun(i) for i in [0, 0, 3, 4])
executed
executed
executed
True
The function all() checks all elements are True and stops executing as soon as a False is encountered:
>>> all(fun(i) for i in [0, 0, 3, 4])
executed
False
>>> all(fun(i) for i in [1, 0, 3, 4])
executed
executed
False
Short-circuiting behavior in Chained Comparison:
Additionally, in Python
Comparisons can be chained arbitrarily; for example, 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).
>>> 5 > 6 > fun(3) # same as: 5 > 6 and 6 > fun(3)
False # 5 > 6 is False so fun() not called and "executed" NOT printed
>>> 5 < 6 > fun(3) # 5 < 6 is True
executed # fun(3) called and "executed" printed
True
>>> 4 <= 6 > fun(7) # 4 <= 6 is True
executed # fun(3) called and "executed" printed
False
>>> 5 < fun(6) < 3 # only prints "executed" once
executed
False
>>> 5 < fun(6) and fun(6) < 3 # prints "executed" twice, because the second part executes it again
executed
executed
False
Edit:
One more interesting point to note :- Logical and, or operators in Python returns an operand's value instead of a Boolean (True or False). For example:
Operation x and y gives the result if x is false, then x, else y
Unlike in other languages e.g. &&, || operators in C that return either 0 or 1.
Examples:
>>> 3 and 5 # Second operand evaluated and returned
5
>>> 3 and ()
()
>>> () and 5 # Second operand NOT evaluated as first operand () is false
() # so first operand returned
Similarly or operator return left most value for which bool(value) == True else right most false value (according to short-circuiting behavior), examples:
>>> 2 or 5 # left most operand bool(2) == True
2
>>> 0 or 5 # bool(0) == False and bool(5) == True
5
>>> 0 or ()
()
So, how is this useful? One example is given in Practical Python By Magnus Lie Hetland:
Let’s say a user is supposed to enter his or her name, but may opt to enter nothing, in which case you want to use the default value '<Unknown>'.
You could use an if statement, but you could also state things very succinctly:
In [171]: name = raw_input('Enter Name: ') or '<Unknown>'
Enter Name:
In [172]: name
Out[172]: '<Unknown>'
In other words, if the return value from raw_input is true (not an empty string), it is assigned to name (nothing changes); otherwise, the default '<Unknown>' is assigned to name.
Yes. Try the following in your python interpreter:
and
>>>False and 3/0
False
>>>True and 3/0
ZeroDivisionError: integer division or modulo by zero
or
>>>True or 3/0
True
>>>False or 3/0
ZeroDivisionError: integer division or modulo by zero
Does Python support short-circuiting in boolean expressions?
Yep, both and and or operators short-circuit -- see the docs.
Short-circuiting behavior in operator and, or:
Let's first define a useful function to determine if something is executed or not. A simple function that accepts an argument, prints a message and returns the input, unchanged.
>>> def fun(i):
... print "executed"
... return i
...
One can observe the Python's short-circuiting behavior of and, or operators in the following example:
>>> fun(1)
executed
1
>>> 1 or fun(1) # due to short-circuiting "executed" not printed
1
>>> 1 and fun(1) # fun(1) called and "executed" printed
executed
1
>>> 0 and fun(1) # due to short-circuiting "executed" not printed
0
Note: The following values are considered by the interpreter to mean false:
False None 0 "" () [] {}
Short-circuiting behavior in function: any(), all():
Python's any() and all() functions also support short-circuiting. As shown in the docs; they evaluate each element of a sequence in-order, until finding a result that allows an early exit in the evaluation. Consider examples below to understand both.
The function any() checks if any element is True. It stops executing as soon as a True is encountered and returns True.
>>> any(fun(i) for i in [1, 2, 3, 4]) # bool(1) = True
executed
True
>>> any(fun(i) for i in [0, 2, 3, 4])
executed # bool(0) = False
executed # bool(2) = True
True
>>> any(fun(i) for i in [0, 0, 3, 4])
executed
executed
executed
True
The function all() checks all elements are True and stops executing as soon as a False is encountered:
>>> all(fun(i) for i in [0, 0, 3, 4])
executed
False
>>> all(fun(i) for i in [1, 0, 3, 4])
executed
executed
False
Short-circuiting behavior in Chained Comparison:
Additionally, in Python
Comparisons can be chained arbitrarily; for example, 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).
>>> 5 > 6 > fun(3) # same as: 5 > 6 and 6 > fun(3)
False # 5 > 6 is False so fun() not called and "executed" NOT printed
>>> 5 < 6 > fun(3) # 5 < 6 is True
executed # fun(3) called and "executed" printed
True
>>> 4 <= 6 > fun(7) # 4 <= 6 is True
executed # fun(3) called and "executed" printed
False
>>> 5 < fun(6) < 3 # only prints "executed" once
executed
False
>>> 5 < fun(6) and fun(6) < 3 # prints "executed" twice, because the second part executes it again
executed
executed
False
Edit:
One more interesting point to note :- Logical and, or operators in Python returns an operand's value instead of a Boolean (True or False). For example:
Operation x and y gives the result if x is false, then x, else y
Unlike in other languages e.g. &&, || operators in C that return either 0 or 1.
Examples:
>>> 3 and 5 # Second operand evaluated and returned
5
>>> 3 and ()
()
>>> () and 5 # Second operand NOT evaluated as first operand () is false
() # so first operand returned
Similarly or operator return left most value for which bool(value) == True else right most false value (according to short-circuiting behavior), examples:
>>> 2 or 5 # left most operand bool(2) == True
2
>>> 0 or 5 # bool(0) == False and bool(5) == True
5
>>> 0 or ()
()
So, how is this useful? One example is given in Practical Python By Magnus Lie Hetland:
Let’s say a user is supposed to enter his or her name, but may opt to enter nothing, in which case you want to use the default value '<Unknown>'.
You could use an if statement, but you could also state things very succinctly:
In [171]: name = raw_input('Enter Name: ') or '<Unknown>'
Enter Name:
In [172]: name
Out[172]: '<Unknown>'
In other words, if the return value from raw_input is true (not an empty string), it is assigned to name (nothing changes); otherwise, the default '<Unknown>' is assigned to name.
Yes. Try the following in your python interpreter:
and
>>>False and 3/0
False
>>>True and 3/0
ZeroDivisionError: integer division or modulo by zero
or
>>>True or 3/0
True
>>>False or 3/0
ZeroDivisionError: integer division or modulo by zero
When I'm trying to check whether a list is empty or not using python's not operator it is behaving in a weird manner.
I tried using the not operator with a list to check whether it is empty or not.
>>> a = []
>>> not (a)
True
>>> not (a) == True
True
>>> not (a) == False
True
>>> True == False
False
The expected output for not (a) == False should be False.
== has higher precedence than not. not (a) == False is parsed as not (a == False).
This is working as expected. Parenthesis added below to clarify how this is being executed:
not (a == True)
# True
not (a == False)
# True
An empty list, a = [], evaluates to False in boolean expressions, but it does not equal False or True. Your expressions in the middle are testing whether it is equal to False or True, so they both evaluate to False, and not False is True.
You can add parenthesis like below to get what you expect:
(not a) == True
# True
(not a) == False
# False
# FOR SETS
a=set([1,2,3])
b=set([4,5,6])
print(a and b) #always prints right side value that is b here
print(a or b) #always prints left side value that is a here
print(b and a)#prints a as its on right
print(b or a)#prints b as its on left
#FOR BOOLEANS
print(False and 0) #prints False as it is on the left
print(0 and False) #prints 0 , same operator is used than why diff output
print(False or '') #prints '' as it is on the right
print('' or False) #prints False as now it is on the right
print(1 or True) #prints 1
print(True or 1) #prints True
print(True and 1)#prints 1
print(1 and True)#prints True
AND always print the left side value and OR always prints the right side value for False type of boolean. Reverse happens with True type of boolean.
When applied to any number of sets OR gives leftmost value and AND gives rightmost value. Why ?
The Python reference answers your question. https://docs.python.org/2/reference/expressions.html#boolean-operations
The expression x and y first evaluates x; if x is false, its value is
returned; otherwise, y is evaluated and the resulting value is
returned.
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.
Values of container type (such as sets and lists) are considered false if they are empty, and true otherwise.
I don't think it's due to left or right side, but more of how and - or are evaluated.
First of all in python 0 is equal to False and 1 to True, but it is possible for True and False to be reassigned, but by default 0 == 0 or 0 == False are both True.
This said, you can now look how and - or operator condition are evaluated.
To summerise:
The and operator is always looking for a False (0) value, if he finds it on the first evaluated parameter then he stop, but if he finds True or 1 he had to evaluate the second condition to see if it's a False. Because False and someting else will always be false. This table might help you, look when i have 0 (False) answer is always 0 (False)
*and* truth table
0 0 = 0
0 1 = 0
1 0 = 0
1 1 = 1
The or is a bit different but with same mechanic:
The or will look for the first True (1) he finds. So if he finds False first he will evaluate the second parameter, if he finds True (1) in first then he stops.
Here when you have a 1(True) answer is always 1(True)
*or* truth table
0 0 = 0
0 1 = 1
1 0 = 1
1 1 = 1
You can look at other operator just google operator truth table and you will have a lot of other and more detailed exemple.
For your exemple:
#FOR BOOLEANS
print(False and 0) #prints False because *and* only need one False
print(0 and False) #prints 0 , because 0 = False and *and* only need one False
print(False or '') #prints '' because *or* is looking for a 1(True) but here both are False so he print the last one
print('' or False) #prints False (same reason as the one above) and he print the last one.
print(1 or True) #prints 1 because it's *or* and he found a True(1)
print(True or 1) #prints True same reason as above 1 = True so...
print(True and 1) #prints 1 because *and* is looking for a False and the first condition is True so he need to check the second one
print(1 and True) #prints True same as above 1 = True so and check for second paramater.
Does Python support short-circuiting in boolean expressions?
Yep, both and and or operators short-circuit -- see the docs.
Short-circuiting behavior in operator and, or:
Let's first define a useful function to determine if something is executed or not. A simple function that accepts an argument, prints a message and returns the input, unchanged.
>>> def fun(i):
... print "executed"
... return i
...
One can observe the Python's short-circuiting behavior of and, or operators in the following example:
>>> fun(1)
executed
1
>>> 1 or fun(1) # due to short-circuiting "executed" not printed
1
>>> 1 and fun(1) # fun(1) called and "executed" printed
executed
1
>>> 0 and fun(1) # due to short-circuiting "executed" not printed
0
Note: The following values are considered by the interpreter to mean false:
False None 0 "" () [] {}
Short-circuiting behavior in function: any(), all():
Python's any() and all() functions also support short-circuiting. As shown in the docs; they evaluate each element of a sequence in-order, until finding a result that allows an early exit in the evaluation. Consider examples below to understand both.
The function any() checks if any element is True. It stops executing as soon as a True is encountered and returns True.
>>> any(fun(i) for i in [1, 2, 3, 4]) # bool(1) = True
executed
True
>>> any(fun(i) for i in [0, 2, 3, 4])
executed # bool(0) = False
executed # bool(2) = True
True
>>> any(fun(i) for i in [0, 0, 3, 4])
executed
executed
executed
True
The function all() checks all elements are True and stops executing as soon as a False is encountered:
>>> all(fun(i) for i in [0, 0, 3, 4])
executed
False
>>> all(fun(i) for i in [1, 0, 3, 4])
executed
executed
False
Short-circuiting behavior in Chained Comparison:
Additionally, in Python
Comparisons can be chained arbitrarily; for example, 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).
>>> 5 > 6 > fun(3) # same as: 5 > 6 and 6 > fun(3)
False # 5 > 6 is False so fun() not called and "executed" NOT printed
>>> 5 < 6 > fun(3) # 5 < 6 is True
executed # fun(3) called and "executed" printed
True
>>> 4 <= 6 > fun(7) # 4 <= 6 is True
executed # fun(3) called and "executed" printed
False
>>> 5 < fun(6) < 3 # only prints "executed" once
executed
False
>>> 5 < fun(6) and fun(6) < 3 # prints "executed" twice, because the second part executes it again
executed
executed
False
Edit:
One more interesting point to note :- Logical and, or operators in Python returns an operand's value instead of a Boolean (True or False). For example:
Operation x and y gives the result if x is false, then x, else y
Unlike in other languages e.g. &&, || operators in C that return either 0 or 1.
Examples:
>>> 3 and 5 # Second operand evaluated and returned
5
>>> 3 and ()
()
>>> () and 5 # Second operand NOT evaluated as first operand () is false
() # so first operand returned
Similarly or operator return left most value for which bool(value) == True else right most false value (according to short-circuiting behavior), examples:
>>> 2 or 5 # left most operand bool(2) == True
2
>>> 0 or 5 # bool(0) == False and bool(5) == True
5
>>> 0 or ()
()
So, how is this useful? One example is given in Practical Python By Magnus Lie Hetland:
Let’s say a user is supposed to enter his or her name, but may opt to enter nothing, in which case you want to use the default value '<Unknown>'.
You could use an if statement, but you could also state things very succinctly:
In [171]: name = raw_input('Enter Name: ') or '<Unknown>'
Enter Name:
In [172]: name
Out[172]: '<Unknown>'
In other words, if the return value from raw_input is true (not an empty string), it is assigned to name (nothing changes); otherwise, the default '<Unknown>' is assigned to name.
Yes. Try the following in your python interpreter:
and
>>>False and 3/0
False
>>>True and 3/0
ZeroDivisionError: integer division or modulo by zero
or
>>>True or 3/0
True
>>>False or 3/0
ZeroDivisionError: integer division or modulo by zero