The wonder of Boolean in python [duplicate] - python

When I was looking at answers to this question, I found I didn't understand my own answer.
I don't really understand how this is being parsed. Why does the second example return False?
>>> 1 in [1,0] # This is expected
True
>>> 1 in [1,0] == True # This is strange
False
>>> (1 in [1,0]) == True # This is what I wanted it to be
True
>>> 1 in ([1,0] == True) # But it's not just a precedence issue!
# It did not raise an exception on the second example.
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
1 in ([1,0] == True)
TypeError: argument of type 'bool' is not iterable
Thanks for any help. I think I must be missing something really obvious.
I think this is subtly different to the linked duplicate:
Why does the expression 0 < 0 == 0 return False in Python?.
Both questions are to do with human comprehension of the expression. There seemed to be two ways (to my mind) of evaluating the expression. Of course neither were correct, but in my example, the last interpretation is impossible.
Looking at 0 < 0 == 0 you could imagine each half being evaluated and making sense as an expression:
>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True
So the link answers why this evaluates False:
>>> 0 < 0 == 0
False
But with my example 1 in ([1,0] == True) doesn't make sense as an expression, so instead of there being two (admittedly wrong) possible interpretations, only one seems possible:
>>> (1 in [1,0]) == True

Python actually applies comparison operator chaining here. The expression is translated to
(1 in [1, 0]) and ([1, 0] == True)
which is obviously False.
This also happens for expressions like
a < b < c
which translate to
(a < b) and (b < c)
(without evaluating b twice).
See the Python language documentation for further details.

Related

Trying to make a program in Python that plays a note based on user input. But whenever I input a single note, it plays them all in order. Why? [duplicate]

When I was looking at answers to this question, I found I didn't understand my own answer.
I don't really understand how this is being parsed. Why does the second example return False?
>>> 1 in [1,0] # This is expected
True
>>> 1 in [1,0] == True # This is strange
False
>>> (1 in [1,0]) == True # This is what I wanted it to be
True
>>> 1 in ([1,0] == True) # But it's not just a precedence issue!
# It did not raise an exception on the second example.
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
1 in ([1,0] == True)
TypeError: argument of type 'bool' is not iterable
Thanks for any help. I think I must be missing something really obvious.
I think this is subtly different to the linked duplicate:
Why does the expression 0 < 0 == 0 return False in Python?.
Both questions are to do with human comprehension of the expression. There seemed to be two ways (to my mind) of evaluating the expression. Of course neither were correct, but in my example, the last interpretation is impossible.
Looking at 0 < 0 == 0 you could imagine each half being evaluated and making sense as an expression:
>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True
So the link answers why this evaluates False:
>>> 0 < 0 == 0
False
But with my example 1 in ([1,0] == True) doesn't make sense as an expression, so instead of there being two (admittedly wrong) possible interpretations, only one seems possible:
>>> (1 in [1,0]) == True
Python actually applies comparison operator chaining here. The expression is translated to
(1 in [1, 0]) and ([1, 0] == True)
which is obviously False.
This also happens for expressions like
a < b < c
which translate to
(a < b) and (b < c)
(without evaluating b twice).
See the Python language documentation for further details.

Incorrect result of boolean comparison [duplicate]

When I was looking at answers to this question, I found I didn't understand my own answer.
I don't really understand how this is being parsed. Why does the second example return False?
>>> 1 in [1,0] # This is expected
True
>>> 1 in [1,0] == True # This is strange
False
>>> (1 in [1,0]) == True # This is what I wanted it to be
True
>>> 1 in ([1,0] == True) # But it's not just a precedence issue!
# It did not raise an exception on the second example.
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
1 in ([1,0] == True)
TypeError: argument of type 'bool' is not iterable
Thanks for any help. I think I must be missing something really obvious.
I think this is subtly different to the linked duplicate:
Why does the expression 0 < 0 == 0 return False in Python?.
Both questions are to do with human comprehension of the expression. There seemed to be two ways (to my mind) of evaluating the expression. Of course neither were correct, but in my example, the last interpretation is impossible.
Looking at 0 < 0 == 0 you could imagine each half being evaluated and making sense as an expression:
>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True
So the link answers why this evaluates False:
>>> 0 < 0 == 0
False
But with my example 1 in ([1,0] == True) doesn't make sense as an expression, so instead of there being two (admittedly wrong) possible interpretations, only one seems possible:
>>> (1 in [1,0]) == True
Python actually applies comparison operator chaining here. The expression is translated to
(1 in [1, 0]) and ([1, 0] == True)
which is obviously False.
This also happens for expressions like
a < b < c
which translate to
(a < b) and (b < c)
(without evaluating b twice).
See the Python language documentation for further details.

Comparison operators and 'is' - operator precedence in python?

So I was looking at some code online and I came across a line (at line 286):
if depth > 0 and best <= -MATE_VALUE is None and nullscore > -MATE_VALUE:
The part I had trouble understanding was the best <= -MATE_VALUE is None.
So I fired up the interpreter to see how a statement such as value1 > value2 is value3 work. So I tried
>>> 5 > 2 is True
False
>>> (5 > 2) is True
True
>>> 5 > (2 is True)
True
My Question
Why is 5 > 2 is True not True? And how do these things generally work?
Thanks.
You're seeing python's operator chaining working
5 > 2 is True
Is equivalent to
5>2 and 2 is True
You can see this in that
>>> 5>2 is 2
Returns True.
First, 5 > 2 is True is equivalent to (5 > 2) and (2 is True) because of operator chaining in python (section 5.9 here).
It's clear that 5 > 2 evaluates to True. However, 2 is True will evaluate to False because it is not implicitly converted to bool. If you force the conversion, you will find that bool(2) is True yields True. Other statements such as the if-statement will do this conversion for you, so if 2: will work.
Second, there is an important difference between the is operator and the == operator (taken from here):
Use is when you want to check against an object's identity (e.g.
checking to see if var is None). Use == when you want to check
equality (e.g. Is var equal to 3?).
>> [1,2] is [1,2]
False
>> [1,2] == [1,2]
True
While this does not have an immediate impact on this example, you should keep it in mind for the future.

Sum of Boolean Operators on Numpy Bool Arrays (Bug?)

I've come across a surprising situation when using numpy's arrays. The following code
(True==True)+(True==True)
returns 2, as one would expect. While
import numpy
Array=numpy.zeros((2,2),dtype=bool)
(Array[0][0]==Array[0][0])+(Array[1][0]==Array[1][0])
returns True. This leads to:
(Array[0][0]==Array[0][0])+(Array[1][0]==Array[1][0])-1
returning 0, while
(Array[0][0]==Array[0][0])-1+(Array[1][0]==Array[1][0])
returns 1, making the sum not commutative!
Is this intended? If so, why?
It would appear that numpy.bool_ behaves slightly differently to vanilla Python bool:
>>> int(True+True) == int(True) + int(True)
True
>>> int(numpy.bool_(1)+numpy.bool_(1)) == int(numpy.bool_(1)) + int(numpy.bool_(1))
False
This is because:
>>> True+True
2
>>> numpy.bool_(1)+numpy.bool_(1)
True
>>> int(numpy.bool_(1)+numpy.bool_(1))
1
Basically, the addition operation for numpy.bool_ is logical, rather than numerical; to get the same behaviour with bool:
>>> int(True and True)
1
This is fine if you only use it for truthiness, as intended, but if you try to use it in an integer context without being explicit about that, you end up surprised. As soon as you're explicit, expected behaviour is restored:
>>> int(numpy.bool_(1)) + int(numpy.bool_(1))
2
I think the problem is th autocasting.
in this case:
(Array[0][0]==Array[0][0])+(Array[1][0]==Array[1][0])-1
Python do:
(Array[0][0]==Array[0][0])+(Array[1][0]==Array[1][0]) = True
True -1 =cast= 1 -1 = 0
In the second case the cast is do it before:
(Array[0][0]==Array[0][0])-1+(Array[1][0]==Array[1][0])
True - 1 + True
(True - 1 =cast= 0)
0 + True =cast again= 0+ 1 = 1
So, it's not a bug. It's a autocasting in diferent parts.

What does this python expression mean

I'm having some problems with the logic below. I was learning about the unittest module and came across this code.
def matches(self, date):
return ((self.year and self.year == date.year or True) and
(self.month and self.month == date.month or True) and
(self.day and self.day == date.day or True) and
(self.weekday and self.weekday == date.weekday() or True))
Which to me looks like it will always end up True. In discussing why the code doesn't work, this difference was discussed:
>>> c=1
>>> c and c == 2 or True
True
>>> c and c == (2 or True)
False
What is the logic for either of "c and c == 2 or True" vs "c and c == (2 or True)"
I known that "==" binds stronger than or, but I don't understand what the entire construct is trying to do. It being used to enable a wildcard. As a part, I guess I need explanation on how and works on numbers (I always thought about it in relation to True/False conditions.
What is the point of the "c and c" part of either expression?
Thanks,
Narnie
or (and and) is a coalescing operator; it always returns one of its operands.
>>> 1 or False
1
>>> 1 or True
1
>>> 0 or False
False
>>> 0 or True
True
>>> 0 or 'a'
'a'
Actually, I figured out what the author was trying to do.
The author likes python, but comes from a C background. He was trying to simulate a ternary operation as in:
bool ? true_value : false_value
The pythonic way of doing this is not
c and c == d or True
stuff, but to use this as of python 2.5 and up:
result = x if a > b else y
If using a lower version of python, do:
result = (y, x)[a>b]
I can't really make sense of that construct either. As you say, it seems like it will always be True. I think the intent was to check for a match only if the corresponding field was set, i.e. truthy, but that doesn't do it.
Whoever wrote that probably wanted something like not x or x==y but didn't quite get there. It would be expressed more clearly as x==y if x else True in today's Python.

Categories