Python "and" operator with ints - python

What is the explanation for this behavior in Python?
a = 10
b = 20
a and b # 20
b and a # 10
a and b evaluates to 20, while b and a evaluates to 10. Are positive ints equivalent to True? Why does it evaluate to the second value? Because it is second?

The documentation explains this quite well:
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.
And similarly for or which will probably be the next question on your lips.
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.

See the docs:
x and y if x is false, then x, else y
non-zero integers are treated as boolean true, so you get exactly the behavior described in the docs:
>>> a = 10
>>> b = 20
>>> a and b
20
>>> b and a
10

In python everything that is not None, 0, False, "", [], (), {} is True
a and b is readed as True and True in this case
the same for b and a
and yes in this case it takes the first value
edit: incomplete as in the comments

Related

What does the following line accomplish? [duplicate]

This question already has answers here:
How do "and" and "or" act with non-boolean values?
(8 answers)
Closed 2 years ago.
So I was trying to solve an algorithm and while trying to find other solutions to it, I found one which was very short and very fast, just one problem...I can't seem to understand what this line is doing:
Full solution:
def proper_fractions(n):
phi = n > 1 and n
print(phi)
for p in range(2, int(n ** .5) + 1):
if not n % p:
phi -= phi // p
while not n % p:
n //= p
if n > 1: phi -= phi // n
return phi
Line that I don't understand:
phi = n > 1 and n
Please forgive me If it is very easy to understand, I just have never come across something like this, I've only used and in if statements, here is what I changed the line to (I think it works like the other one, but not sure how the other one does exactly what the following line which I changed does):
phi = n if n > 1 else False
Please could someone clear-up how the line that I don't understand works?
As can be seen in the Python docs, Python logical operators are not necessarily "purely Boolean". In particular, and and or are not actually guaranteed to return True or False. Instead, they return one of their operands. Here's how Python defines the value of x and y:
if x is false, then x, else y
"False" in this context does not mean that x has to be the value False. Instead, it just has to be anything with a falsy value, like a zero of any type or an empty sequence or collection.
In this case, when n > 1 evaluates False, the operator short-circuits and returns n > 1, AKA False. But if n > 1 evaluates True, the operator simply returns n without modifying it in any way, as the docs describe.
The truth table for a and b looks like this:
True and True == True
True and False == False
False and True == False
False and False == False
We can observe three things:
When a is True, the result is always the same as b.
When a is False, the result is always False, in other words, it is always the same as a.
When a is False, b is completely irrelevant, so we don't even need to evaluate it.
Note that in Python, True and False are not the only objects that have a boolean value. In fact, every single object in Python has a boolean value. E.g. 0 has a falsey value, "Hello" has a truthy value, and so on.
So, with the optimizations we discovered about the truth table, and the added condition that we need to handle values other than True and False, we can construct the following, revised, truth table:
a and b == a # if `a` is *falsey*
a and b == b # if `a` is *truthy*
This matches up with the documentation of and:
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.
Similar reasoning applies to or:
a or b == b # if `a` is *falsey*
a or b == a # if `a` is *truthy*
So, the result of the line in question:
phi = n > 1 and n
will be that phi is assigned False if n <= 1 and n if n > 1.
The further computation that is performed with phi in turn works because False is equivalent to 0 in a numeric context, i.e.
False + 1 == 1
False - 1 == -1
This makes the rest of the algorithm work, which contains statements like:
phi -= phi // p
Where arithmetic is performed with the value of phi.
See the documentation on the numeric types for details, which contains the following statement [bold emphasis mine]:
There are three distinct numeric types: integers, floating point numbers, and complex numbers. In addition, Booleans are a subtype of integers.
From section 6.11 of 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.
Note that neither and nor or restrict the value and type they return to False and True, but rather return the last evaluated argument. This is sometimes useful, e.g., if s is a string that should be replaced by a default value if it is empty, the expression s or 'foo' yields the desired value. Because not has to create a new value, it returns a boolean value regardless of the type of its argument (for example, not 'foo' produces False rather than ''.)
So it first check if n > 1, if it is true, then it return s n, otherwise it returns False.
First, it's first checking if the first evaluation is True or False (Null value are considered false). Then if it's True, will return the second value. In this case, n.
More details:
> if n = 3
> 1. phi = n > 1 and n
> 2. phi = 3 > 1 and 3
> 3. phi = True and 3
> 4. phi = 3

Booleans with numbers in Python

I came across this implementation of gcd in Python:
def gcd(x,y): return y and gcd(y, x % y) or x
What I don't understand is how the boolean is working in the return? After trying some numbers in the interpreter I noticed that and always returns the number on the right, while or returns the number on the left. Why is this? Also, can you walk me step by step through a simple call of this function so I can understand what is happening?
This is because of how and and or operators evaluate in Python.
From 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.
They do not return True or False , they return the last evaluated value , and that is why we can write things like -
s = s or "Some default value"
To default the value of s if its None or empty string or empty list, or 0.
Basically, or returns the first non false-like value ( where false-like values are 0, or None or Empty string/list/tuple, etc ) Or the last false-like value if all the values are false-like. Example -
In [1]: 0 or 10
Out[1]: 10
In [2]: 5 or 0 or 10
Out[2]: 5
In [7]: 0 or '' or [] or ()
Out[7]: ()
And, and returns the first false-like value, or the last true-like value , if all the values are true-like. Example -
In [3]: 0 and 10
Out[3]: 0
In [4]: 5 and 10
Out[4]: 10
In [6]: 5 and 0 and 10
Out[6]: 0
In your case, it works as -
if y is 0 it returns x (irrespective of the value of x) .
otherwise it computes gcd(y, x%y) if that is non-zero returns it. (Though it would never really be 0)
if the result of gcd(y, x%y) is 0, then it returns x .
This is called "short circuiting." Whenever Python knows what the result of a boolean expression is going to be, it stops evaluating. This is an optimization, but it also makes for some handy idioms, like assigning default values.
def do_a_thing(maybelist=None):
# this is done all the time when you want the default argument to be
# a list, but you don't want to make the mistake of a mutable default argument
maybelist = maybelist or []
The implementation example you gave is confusing to someone who doesn't know about Euclid's Algorithm for calculating gcd's, because it's not obvious how the heck it actually calculates the gcd. I would say that that is an example of someone abusing short circuit evaluation.
In Python, the only integer that defaults to False is zero. Logical values perform short-circuiting, as one of the comments say.
With the statement:
a and b
If 'a' evaluates to False, then 'b' does not need to be evaluated, so the result of the expression is 'a', but if 'a' evaluates to True, then b still needs to be evaluated, so b will be the result of the expression unless a evaluates to False.
`or' works the other way around, which makes sense if you think about it.
and and or are not strictly Boolean operators in Python. x and y and x or y will always evaluate to either x or y, depending on the "truthiness" of the value. False values are numerical zeros, empty strings, and empty containers; all other values are true. This means that
x and y == x if x is false; y is not evaluated
x and y == y if x is true
x or y == x if x is true; y is not evaluated
x or y == y if x is false
The only time either evaluates to an actual Boolean value is when the x or y value involved is an actual Boolean value.

Trying to understand a simple feature about 'and' command in python. Can anyone clarify it? [duplicate]

This question already has answers here:
and / or operators return value [duplicate]
(4 answers)
What does "variable or 0" mean in python?
(4 answers)
Closed 7 years ago.
In Python, if I write
z = 1 and 2
print z
Then it yields "2".
But if I write
z = 0 and 2
print z
Now, it yields "0".
It may not be much important in real life problem, but I'm trying to understand the logic here.
0, [], "" are all false-ish (they are treated as False in a python condition). and returns the first false-ish value or the last one. This is called short-circuit evaluation. That's why in one case it returns 2 (the last) and in the other it returns 0 (the false-ish).
In fact if you think about the logic operation, you can short-circuit this behaviour:
x and y (with x false-ish) -> x
x and y (with x true-ish) -> y
When plugged into a condition it will evaluate as:
In the first case it evaluates the boolean result of x which is False. This is the correct result for the and operation, since False and y = False for any y.
In the second case it evaluates the boolean value of y. Since x is True, the result of and should be False when y is False and True when y is True (it reflects the value of y).
c = a and b
is the same as
if a:
c=b
else:
c=a
I think more interesting is or:
c = a or b
is the same as
if a:
c=a
else:
c=b
Note also that if a: is a short way of if bool(a):. bool returns False for this objects/values:
None, 0, False, "", [], tuple(), dict(), set()
As you can see, they are all somehow empty...
The and operator in python short circuits. That is: it only evaluates enough operands (from left to right) as are necessary to determine whether the outcome is True or False. The result of and is False so in the second case, where 0 evaluates to False, and returns 0, but as 1 is True, the second operand must also be evaluated and returned.
0 is treated as False and anything above zero is treated as True so z = 1 and 2 sets z equal to 2 and z = 0 and 2 is 0 because it evaluates to False.

Quirky output python

Please explain below, I think it should have printed True or False since these are boolean expressions. And why it's printing 2 1 and then 1 2
print 1 and 2
print 2 and 1
print 1 or 2
print 2 or 1
output:
2
1
1
2
Why you think the result must be a boolean type ?
from python wiki :
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 neither and nor or restrict the value and type they return to False and True, but rather return the last evaluated argument. This is sometimes useful, e.g., if s is a string that should be replaced by a default value if it is empty, the expression s or 'foo' yields the desired value. Because not has to invent a value anyway, it does not bother to return a value of the same type as its argument, so e.g., not 'foo' yields False, not ''.

Python: what is the operation that returns 6 for the expression (2 and 2*3)?

My first question is what is the more abstract question for the question: 'what is the operation that returns 6 for the expression (2 and 2*3)? Please feel free to retitle my question appropriately.
My second question is what is it that is going on in python that returns 6 for (2 and 2*3). There seems something elegant going on here, and I'd like to read up on this operation.
From the Python language reference:
Note that neither and nor or restrict the value and type they return to False and True, but rather return the last evaluated argument.
As such, 2 and 2*3 means it first evaluates bool(2), which evaluates to True, and then it evaluates bool(2*3) which evaluates to True. Therefore it'll return the last evaluated argument, which is 2*3 (6).
According to the python docs
x and y : if x is false, then x, else y
First you have to read this and then you have to read this. :)
After that you will know that and is a boolean operator, that tries to convert it's first operand to boolean. So if you read the first thing you will see that 2 is converted to True.
The third thing you need to know is that the and operand will return it's first argument if it is converted to False and it's second argument if it evaluates to True.
So basically
z = x and y
Can be translated to:
if x:
z = y
else:
z = x
And now you understand everything. :)
2 is evaluated to True and then and operator returns the value of it's second argument which is 6.
Applying lazy evaluation, python return for a and b a if a evaluates to False and b if a evaluates to True.
Hence 2 evaluates to True, 2 and 2*3 return 2*3 which equals 6.
Basically it's same as 2 and 6.
How it works? and returns first element if it's considered False (False, 0, [] ...) and return second otherwise
This is to do with how Python evaluates the expression x and y. It returns y if x is True, and x if x if False.
So, in case of 2 and 2 * 3, since 2 is evaluated to True, it would return the value 2 * 3, which is 6.
In case of and operation between multiple operands, it returns the 1st non-True value, and if all the values are True, it returns the last value.
Similarly, for or operator, the expression say, A or B or C, returns the 1st True value. And if all the values are False, it returns the last value.

Categories

Resources