logical python comparison, evaluates False when it should be true [duplicate] - python

This question already has answers here:
How to test multiple variables for equality against a single value?
(31 answers)
Closed 6 years ago.
Why does the following evaluates to False in Python?
6==(5 or 6)
False
'b'==('a' or 'b')
False

The first expression evaluates (5 or 6) first, which evaluates to 5 because 5 is truthy. 5 is NOT equal to 6 so it returns False.
The second expression evaluates ('a' or 'b') first, which evaluates to 'a' for the same reason as above. 'a' is NOT equal to 'b' so it returns False.
A good example to explain this would be to try to put a falsey value as the first part of the or expression like 6 == ([ ] or 6) or 6 == (None or 6). Both of these will return true because the or statement will evaluate to the truthy value (in each case it is 6).
There are a couple of ways to create the statement I think you want. The first would be to use in like 6 in (6,5). The second way would be to expand your boolean expression to read like this (6 == 5) or (6 == 6). Both of these will return True.

The condition within parentheses is evaluated first. So
6==(5 or 6)
evaluates to
6==(5) # since 5 != 0 (True), the second operand is not evaluated
which is False. Same goes for the second one. ('a' != None)

Try:
>>>6 == (6 or 5)
True
What's going on? Try:
>>5 or 6
5
I'm not totally sure why "5 or 6" evaluates to 5, but I would just try writing that expression differently.

But there is a caveat:
>> 5 == (0 or 5)
True
Because 0 is not truth-worthy, hence the bracket result in 5.

Related

why is this conditional statement using comparison operators incorrect? [duplicate]

This question already has answers here:
Why does "a == x or y or z" always evaluate to True? How can I compare "a" to all of those?
(8 answers)
How to test multiple variables for equality against a single value?
(31 answers)
Comparison operators and 'is' - operator precedence in python?
(2 answers)
Check if all values in list are greater than a certain number
(9 answers)
Closed 6 months ago.
This is a small element of a larger script. Through trial and error I have found that this is the offending line:
>>> print('lower than all') if (3 < (2 and 9 and 9)) is True else print('false')
lower than all
This is clearly incorrect. However changing to this gives the right answer:
>>> print('lower than all') if 3 < (2 and 9 and 9) is True else print('false')
false
I have simplified the example, in reality all the numbers are variables being checked. I really don't understand the difference here!
Again why does this work correctly?!
>>> print('lower than all') if 3 < 2 and 9 and 9 is True else print('false')
false
If you see this chunk, it returns 9
>>> 2 and 9 and 9
9
To understand this, take a look at how the and operation between integers works. From the official doc:
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.
In this case, 2 is true, 9 is true and the final 9 is also true. Here, the last 9 is y and that's the value being returned.
Try out 2 and 1 and you'll see 1 as the result.
Due to this, your statement
print('lower than all') if (3 < (2 and 9 and 9)) is True else print('false')
Actually becomes
print('lower than all') if (3 < 9) is True else print('false')
And prints 'lower than all'

or operator does not returns boolean type [duplicate]

This question already has answers here:
How do "and" and "or" act with non-boolean values?
(8 answers)
How to test multiple variables for equality against a single value?
(31 answers)
Closed 1 year ago.
enter image description here
i'm now working on if statements
this is my code
a = [1,2,3]
print(4 or 5 in a)
and the outcome is 4 not False
this code returns what i have expected
a = [1,2,3]
print((4 or 5) in a)
I can't understand how or operator works
why the return is integer..? not True or False
If there are multiple conditions in an if statement, if the first statement is correct, it doesn't check the second statement. Since 4 is true, it doesn't check if 5 is in the variable a or not. Therefore, it returns the value 4 and not False
In this case you have expression written incorrectly and as a result it evaluates the way it does. What you should have written was:
>>> a = [2, 1, 4]
>>> 4 in a or 5 in a
Out[18]: True
In your case the expression evaluates only the condition 4 or 5 which evaluates to 4 as the first truthy value.
>>> 4 or 5 in a
Out[27]: 4
>>> 4 or 5
Out[28]: 4
In fact, variable a is completely skipped here and not evaluated at all. We can do the same but using variable b that has never been defined in this session and we get 4 instead of UnboundLocalError:
>>> 4 or 5 in b
Out[31]: 4
Similarly we can test this behaviour. When you compare two truthy values the result is always the first one the interpreter encounters.
>>> 'a' or 'b'
Out[29]: 'a'
>>> 'd' or 'a'
Out[30]: 'd'
I suggest reading docs on boolean operators in Python to get a better understanding of what's happening (for example, here). It can get confusing.

Why does this boolean expression evaluate to False? [duplicate]

This question already has answers here:
python operator precedence of in and comparison [duplicate]
(3 answers)
Closed 3 years ago.
Can someone explain to me why the Python interpreter evaluates this expression to be False?
1 in [1] == True
I would expect that 1 in [1] would evaluate to True, and obviously True == True would be True. However this isn't what happens - the expression is False. Why does this happen?
== and in are both comparison operators. And when you have multiple comparison operators like this, Python considers it a chained comparison. For example, 1 < x < 10 is equivalent to 1 < x and x < 10.
In your case, 1 in [1] == True is equivalent to (1 in [1]) and ([1] == True), which evaluates to False.
If you have an expression like this python split it to more statements. In fact:
1 in [1] == True equals to: (1 in [1]) and ([1] == True)
Right side is false since [1] != True and whole sentence is false

Using IF, AND, OR together with EQUAL operand together in Python [duplicate]

This question already has answers here:
How to test multiple variables for equality against a single value?
(31 answers)
Closed 6 years ago.
I'm trying to create a function where the given value (passed as a string) is checked to see if the number of digits is either 4 or 6, and that it is a number.
My first impulse was to go with this code:
def number(x):
if (len(x) == (4 or 6)) and x.isdigit():
print "True"
else:
print "False"
This code above only passes the first test below...I don't understand why it passes this but none of the other tests:
number("1234")
Only when I separate out the len() functions will it work properly.
def number(x):
if (len(x) == 4 or len(x) == 6) and x.isdigit():
print "True"
else:
print "False"
## Checks
number("1234")
number("123456")
number("abcd")
number("abcdef")
number("1")
number("a")
The above code passes all tests.
So my questions are:
What's going on here?
Any way to write cleaner code for this?
Thank for the help!
** Not a duplicate question because although this question has the same underlying concepts regarding boolean operators, the problem itself is different due to the usage of len(), isdigit(), and the additional question of how best to improve it (someone commented the usage of return). Definitely adds another perspective to the other question though.
It helps to examine the logic of this line:
if (len(x) == (4 or 6)):
The (4 or 6) clause contains a logical or short circuit. The value 4 is true, so it is evaluated and returned to the == relational comparison.
The way that or works is that its lefthand side is evaluated for Boolean truth, and its value is returned if true. If the lefthand side is not Boolean true, then the righthand side is evaluated and its value is returned.
Because the lefthand side of the 4 or ... is true in a Boolean sense, the righthand side is never evaluated. Python doesn't even look past 4 or. If the left-hand value were a false value (such as 0), then the right hand side of the or would be evaluated.
To see this in action, try print 4 or 6. The output will be 4.
So since the 4 is a hard-coded true value, your comparison is semantically the same as if (len(x) == 4) -- that is, since 4 is true, 6 is never evaluated.
What I suppose you really want to know is if len(x) is either 4 or 6. You could put that to code in a couple of ways:
if(len(x) == 4 or len(x) == 6 ...
if(len(x) in (4,6) ...
You can use the in operator like so:
def number(x):
if len(x) in (4, 6) and x.isdigit():
print "True"
else:
print "False"
where in checks for containment in a given container. Note that 4 or 6 on their own evaluate to something undesirable, which is why your first code segment fails. You can check it out on the python shell:
>>> 4 or 6
4
You probably wanted to write
if (len(x) in (4, 6)) and x.isdigit():
Instead of
if (len(x) == (4 or 6)) and x.isdigit():
Short answer: len(x) in [4, 6] or len(x) == 4 or len(x) == 6.
"or" is a boolean, or logical choice. (4 or 6) is guaranteed to resolve to a non-zero (true) value. In this case, it resolves to 4, so your test case passes.
I'll go ahead and answer
Any way to write cleaner code for this?
Yes. Return the boolean value, rather than printing a string.
def number(x):
return len(x) in {4, 6} and x.isdigit()
print(number("1234")) # True
Then, it is simple do use your method in a if-statement without string comparison.
The trouble is in your or statement.
Any value greater than one will evaluate to True when you put it in a conditional. So (4 or 6) will always resolve to true.
You could use the in statement above or you could just use two =='s:
if (len(x) == 4 or len(x) == 6) and x.isdigit()
It's a bit wordier, I find it easier to read.

Boolean logic in Python [duplicate]

This question already has answers here:
Is False == 0 and True == 1 an implementation detail or is it guaranteed by the language?
(3 answers)
Closed 8 years ago.
Can someone help to explain the following:
1 and 5
5 and 1
The above gives 5 and 1 respectively. Q1: Why is the and operator not commutative?
Next:
1==True # gives True
However:
5==True
5==False
both give False. Q2: Why?
https://docs.python.org/2/library/stdtypes.html section 5.1 says "... All other values are considered True", so 5 should be True.
From the documentation:
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.
Note that here, if x is false means if bool(x) == False.
The answer to your first question about and is that the result of the and is the value of the first expression if it is False-like (0, False, None, etc.), otherwise it is the value of the second expression. A bunch of programming languages share this sort of construct; in some languages like Bash and Perl it's idiomatic to rely on it extensively. In Python we mostly use and for regular boolean logic and rely on it less often for short-circuiting.
As for 1==True being true but 5==True being false, well, frankly I wish 1==True also returned false but obviously it's too late to change it now. :)
In answer to your second part:
It's true that all non-zero integers are "Truthy" but this does not mean that 5 == True will return True. The == operator is comparing value and, when comparing values, 5 is not equal to True. If you compare bool(5) == True then that will return True. When you do if 5: what you actually are doing is if bool(5):.
The reason that 1 == True returns True is that in Python the boolean class is a subclass of int, with True being represented by 1 and False being represented by 0. So 1 == True returns True because they are equal.
Note that, as discussed in this question, this is NOT GUARANTEED in Python 2.x as True and False can be re-defined. In Python 3.x they are keywords which will always be equal to 1 and 0, respectively.

Categories

Resources