Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why this conditional does not raise an Exception: (1==0 <= 1/0) == False? How Python parses this?

How come this is evaluate to False?

1==0 <= 1/0

First note that in Python:

bols = [False, True] for A in bols: for B in bols: print(f'{str(A):>5}, {str(B):>5}, {str(A<=B):>5}') Outputs:

False, False, True False, True, True True, False, False True, True, True If you are familiar with boolean logic this hould be natural to you.

Now it gets weird:

print(1==1 <= 1/1, 1==0 <= 1/1)

Out: True, False

And now it gets weirder:

print(1==0 <= 1/0)

Out: False

Why this last one does not throw an exeption?

My first guess is becasue of parsing issues. For example, a previous comparasion we can fix adding parenthesis:

print(1==1 <= 1/1, (1==0) <= 1/1)

Out: True, True

But if this issue is a parsing problem, how come python does not raise an exception when we divide by 0?

If we add parenthesis to the last comparasion we can force Python to raise ZeroDivision Exeption:

print((1==0) <= 1/0)

Out: ZeroDivisionError: division by zero

Also, why the following raises an Exception?

1==1 <= 1/0

Out: ZeroDivisionError: division by zero

NB: This works with other exceptions as well, probably with any, since python does not evaluate the right hand side of the inequality.

Why?

I would understand if the laizy evaluation were True, but why False? Feels like a bug in Python.

like image 246
zeh Avatar asked Mar 05 '23 20:03

zeh


1 Answers

1==0 <= 1/0

1/0 is never evaluated. The expression triggers chained comparison in Python. It is evaluated as:

(1 == 0) and (0 <= 1/0)

Logical and short-circuits when a False value is reached, so the second condition is never tested. Since 1 == 0 evaluates to False, the result is False.


1==1 <= 1/0

In the same vein, this is evaluated as:

(1 == 1) and (1 <= 1/0)

Since the first expression is True, the second one is evaluated. This leads to ZeroDivisionError.


(1==0) <= 1/0

Parentheses have higher priority than comparison operators. So chained comparisons are not triggered here. The expression is evaluated as False <= 1/0. Of course, the comparison will fail with ZeroDivisionError.


1==1 <= 1/1, 1==0 <= 1/1

Here you are defining a tuple of results. A tuple is implicit by the existence of a comma separating your two expressions. The first, 1==1 <= 1/1, evaluates to True since True <= 1. The second, 1==0 <= 1/1, evaluates to True since False <= 1.

These comparisons work since bool is a subclass of int, so True is equivalent to 1 and False is equivalent to 0.

like image 120
jpp Avatar answered Mar 23 '23 00:03

jpp