0

I tried to understand what's happening below but I can't...

get_val = lambda: print('abc') or 5
print(1 is None == get_val())  # It prints False
print((1 is None) == get_val())  # It prints 'abc' then False
print(1 is (None == get_val()))  # It prints 'abc' then False

Note that I noticed this by debugging something like if a is None == f() is None which is clearly not good, but it's surprising to me that f() is not executed at all.

Thank you a lot...

Nan Hua
  • 31
  • 4
  • The comparison will be shortcircuited, since `1 is None` is False already, there is no need to run the last expression, which is the function call. – Jan Christoph Terasa Jul 03 '20 at 07:07

1 Answers1

2

Both the is and == operators are comparison operators. Therefore, they will be chained when you use them like the first print call.

From the docs

Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

Formally, if a, b, c, …, y, z are expressions and op1, op2, …, opN are comparison operators, then a op1 b op2 c ... y opN z is equivalent to a op1 b and b op2 c and ... y opN z, except that each expression is evaluated at most once.

So, 1 is None == get_val() is equivalent to (1 is None) and (None == get_val()) Since 1 is None is false, due to short-circuiting, (None == get_val() is never executed, and abc is never printed.

And finally:

a is None == f() is None

Is equivalent to:

(a is None) and (None == f()) and (f() is None)

Since a is None is probably false, then f() will never get evaluated. Note, though, when it is chained, as the doc's state, f() is only actually evaluated once.

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172