Hey my question is pretty basic, while I was playing around in the expresssion
3 and 3%3 == False returns True
BUT
0 and 0%3 == False returns 0
With other numbers instead of 0 the result is either True or False but never 0.
I wanted to know what does make 0 so special.
From all integers, 0 is the only one that is evaluated to False. In fact, False's value is 0 (you can try print False + 0) - so you get the second expression's result (X % Y == Z which is True/False).
Any other integer and the first argument is what is returned (int) since and stops and returns the first expression false-y expression (there is no need to proceed once you hit a single False in an and expression). It does not matter what the next expression is since it's never even evaluated.
First, 3%3 is equal to 0. Next, bool is a subclass of int, with 0==False and 1==True. Then, you have 3 and 3%3==False, which is 3 and 0==False, which is 3 and True.
So now that leaves us with the way short-circuiting works: with and, if the first value is falsey, it returns the first value. If the first value is truthy, it returns the second value. Since 3 is truthy, it returns the second value, True.
3 and 3%3==False
3 and 0==False
3 and True
^ truthy
3 and True
^ returned
For the next one, 0%3 is the same 0 as in the previous one, which turns out the same. However, the first value, 0, is a falsey value, so, since it's combined with and, the first value, 0, is returned.
0 and 0%3==False
0 and 0==False
0 and True
^ falsey
0 and True
^ returned
TLDR: Boolean operators in Python evaluate to the first value that unambiguously determines their value.
So, let's look at 3 and 3 % 3 == False, which is equivalent to 3 and ((3 % 3) == False). An and expression has a boolean value of True only if both the values have a boolean value of True; otherwise it has a boolean value of False. First it checks 3, which returns 3, which has a boolean value of True (bool(3) is True). Then it checks (3 % 3) == False, which returns True, which of course has a boolean value of True. Now that the right side of the and has also been shown to have a boolean value of True, that's what is 'returned' by the and expression.
The reason that 0 and 0 % 3 == False returns 0 is because the first value in the and expression is checked first. Since the first value is 0, which has a boolean value of False, there's no need to check the rest of the and expression. So 0 is returned by the and expression.
Here's some code:
>>> x = 5 or 3
>>> print(x)
5
>>>
>>> y = 0 and 7
>>> print(y)
0
>>>
>>> z = 1 and 7
>>> print(z)
7
Related
I'm learning about logic gates and was messing around with them when I found something interesting. This is my code:
for i in range (4):
p = math.floor(i/2)
q = i % 2
a = p and q
b = not(not(p or q) or not(q) or not(p))
print(str(p) +"\t"+ str(q) + "\t"+ str(a)+"\t"+str(b))
And this is the result:
0 0 0 False
0 1 0 False
1 0 0 False
1 1 1 True
Why doesn't Python either always print a 1 or a 0 or always print True or False?
math.floor returns a number.
Operators between two numbers (such as modulo) also return numbers.
not returns a bool, not an int
Because not has to create a new value, it returns a boolean value regardless of the type of its argument - spec
If you want it to be an int (and simplify the print statement)
print('\t'.join(map(str, [p, q, a, int(b)])
The not unary operator always returns a bool value. It needs to, as it needs to return the boolean inverse of whatever value it was passed, which is always a new value (not its argument).
The real odd part of your chart is actually the third column, which shows that the and operator does return numbers if it's passed them on both sides. You might expect and to be a boolean operator just like not, but it's slightly different. The reason is that and always returns one of its arguments. If the first argument is falsey, that value is what is returned. If the first argument is truthy, the second argument is returned.
You can see this if you test with values other than just 0 and 1:
print(3 and 2) # prints 2
print([] and [1,2]) # prints []
The or operator also does this (in a slightly different manner), but that's covered up in your calculation of b by the not calls.
This behavior of and and or is called short-circuiting. It's big advantage is that it lets Python avoid interpreting expressions it doesn't need to get the value of the boolean expression. For instance, this expression will not call the slow_function:
result = falsey_value and slow_function()
It also lets you guard expressions that would cause exceptions if they were evaluated:
if node is not None and node.value > x:
...
If the node variable is None in that code, evaluating node.value would give an AttributeError (since None doesn't have a value attribute). But because and short circuits, the first expression prevents the second expression from being evaluated when it's invalid.
I thought I understood these two singleton values in Python until I saw someone using return l1 or l2 in the code, where both l1 and l2 are linked list object, and (s)he wanted to return l1 if it is not None, otherwise, return l2.
This piece of code is good because it is quite short and seems easy to understand. Then, I write some code to figure out what is going one here.
print ( True or 'arbitrary' ) #True
print ( False or 'arbitrary') #arbitrary
print ( None or 'arbitrary' ) #arbitrary
The printed results are as expected. However, when I try to put None and False together. Something really weird happened.
print ( False or None ) #None
print ( None or False ) #False
print ( None or False or True) #True
So, my guess the rules of return A or B are:
return the first True (not None, Not False) value in order (First A and then B)
if there is no True value, then the last value will be returned.
At last, I run this code to verify my guess.
print ( None or False or True or None) # True
print ( None or False or None) # None
print ( False or None or False) # False
The results seem to prove my theory. But anyone has more explanation?
Also, I got something interesting when I use and. Why?
print ( None and False) #None
print ( False and None) #False
The short answer is that 'and' returns the first false value or last true value and 'or' returns the first true or last false answer.
>>> None or False
False
>>> False or None
>>> False and None
False
>>> None and False
...
>>> 0 or 3 or 4
3
>>> 5 and 0 and 6
0
>>> 5 and 0 or 6
6
>>> False or {} or 0
0
>>> 3 and 4 and 5
5
In python an empty string, set, list, dictionary, other container or 0 are all equivalent to False for logical operations. Non-empty collections and non-zero numbers are logically True.
For an 'or' the last expression will be returned if no logically True expression was previously encountered. That expression will logically evaluated by the above rule.
No need to guess. For or, Python's Reference Manual says
"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."
In other words, x if x else y, where x is evaluated just once and y only if needed.
For and, change 'true' to 'false'.
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 other words, x if not x else y, where x is evaluated just once and y only if needed.
This question already has answers here:
How do "and" and "or" act with non-boolean values?
(8 answers)
Closed last month.
While reading about logical operators in python, I came across the following expressions:
5 and 1
output: 1
5 or 1
output: 5
Can anyone explain how this is working?
I know that the operands of the logical operators are Boolean
that is well documented:
x or y if x is false, then y, else x
x and y if x is false, then x, else y
both short-circuit (e.g. or will not evaluate y if x is truthy).
the documentation also states what is considered falsy (False, 0, None, empty sequences/mappings, ...) - everything else is considered truthy.
a few examples:
7 and 'a' # -> 'a'
[] or None # -> None
{'a': 1} or 'abc'[5] # -> {'a': 1}; no IndexError raised from 'abc'[5]
False and 'abc'[5] # -> False; no IndexError raised from 'abc'[5]
note how the last two show the short-circuit behavior: the second statement (that would raise an IndexError) is not executed.
your statement that the operands are boolean is a bit moot. python does have booleans (actually just 2 of them: True and False; they are subtypes of int). but logical operations in python just check if operands are truthy or falsy. the bool function is not called on the operands.
the terms truthy and falsy seem not to be used in the official python documentation. but books teaching python and the community here do use these terms. there is a discussion about the terms on english.stackexchange.com and also a mention on wikipedia.
This is because of the short-circuit evaluation method.
For the and, all of the clauses must be True, so all of them must be evaluated. Once a False is encountered, the whole thing evaluates to False, we don't even need to evaluate the next ones.
>>> 1 and 2
2
>>> 2 and 1
1
>>> 1 and 2 and 3
3
>>> 1 and 0 and 2
0
>>> 0 and 1 and 2
0
But for or, any of the clauses being evaluated to True is enough for the whole thing to be True. So once it finds something to be True, the value of the whole thing is decided to be True, without even evaluating the subsequent clauses.
>>> 0 or 1
1
>>> 1 or 0
1
>>> 1 or 2
1
>>> 2 or 1
2
>>> 0 or 0 or 1
1
>>> 0 or 1 or 2
1
This is called short circuiting or lazy evaluation. Example, if you have "a or b" and a meets the criteria, then python will output it. Conversely, if you have "a and b" and "a" does not meet the criteria, then python will stop evaluating it since it cannot be satisfied.
In the first case when the and keyword is there, it is the second value that determines whether it is logically true or not, provided the first number is non-zero. Thus the second value is printed eventually.
In the second case, the keyword is or so when the first non-zero operand is encountered, since it makes the statement logically true, it is printed onto the output screen.
It is an example of lazy evaluation.
This question already has answers here:
Using "and" and "or" operator with Python strings
(6 answers)
Why do 'and' & 'or' return operands in Python?
(4 answers)
Closed 5 years ago.
Below is the scenario.
>>> False and 0
=> False
>>> 0 and False
=> 0
Both the conditions are same, but why is it returning different results?
>>> 0 or False
=> False
>>> False or 0
=> 0
Similarly, both the conditions should return same results, but why are they different?
The same applies in case of True and 1
In python, theand, or operators do not return boolean. They return the last thing evaluated. Since they are short circuit operators, the last thing that need to be evaluated for the expression 0 and False, is0. Similarly, for 0 or False, the last thing that needs to be checked is the second operand, False.
From the python documentation:
x or y: if x is false, then y, else x
x and y: if x is false, then x, else y
not x: if x is false, then True, else False
Python conditional checking uses Short-Circuit Evaluation. This means the following:
False and 0
It is executing an and statement, so both elements must evaluate to 1. Since False doesn't, it does not check for the second one and it returns False. This also applies for 0 and False, but since 0 is the first element it returns 0.
False or 0
In this case it is performing an or evaluation so one of the elements must evaluate to 1 (or True). Since False doesn't, it checks for the second operator (0) which neither evaluates to 1, so it returns it. The same applies for 0 or False.
Here you have another approach that clears out any doubt. Using 0 or "Text" it returns "Text" as it evaluates to True.
or is a short-circuit operator, so it only evaluates the second argument if the first one is false. In the case, False or 0, first argument is evaluated to False, then second argument is evaluated, which is 0, and returns 0. This is valid for both the cases(0 or False too).
and is also a short-circuit operator, so it only evaluates the second argument if the first one is true. In the case False and 0, the first argument is evaluated to False, then the second is not evaluated and returns the first argument and vice versa.
For more clarification, refer the docs.
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.