4

Consider

1 in [] == False

On a very quick glance, it appears that this will raise a TypeError: bool is not iterable, but it actually executes (and evaluates to False if you are curious, which is also a bit surprising).

However,

1 in [1] == False

is also evaluating to False.

It is interesting to note that 1 in [] == False does not:

  • Evaluate as 1 in ([] == False) - This causes the expected TypeError mentioned above.
  • Evaluate as (1 in []) == False - This can be confirmed by (1 in []) == False which outputs True, compared to 1 in [] == False which evaluates to False.

The only output that does make sense is (1 in [1]) == False which is False.

dis.dis outputs:

dis.dis('1 in [] == False')
print()
print()
print()
dis.dis('(1 in [1]) == False')
print()
print()
print()
dis.dis('1 in ([] == False)')

outputs

  # 1 in [] == False
  1           0 LOAD_CONST               0 (1)
              2 BUILD_LIST               0
              4 DUP_TOP
              6 ROT_THREE
              8 COMPARE_OP               6 (in)
             10 JUMP_IF_FALSE_OR_POP    18
             12 LOAD_CONST               1 (False)
             14 COMPARE_OP               2 (==)
             16 RETURN_VALUE
        >>   18 ROT_TWO
             20 POP_TOP
             22 RETURN_VALUE


  # (1 in [1]) == False
  1           0 LOAD_CONST               0 (1)
              2 LOAD_CONST               1 ((1,))
              4 COMPARE_OP               6 (in)
              6 LOAD_CONST               2 (False)
              8 COMPARE_OP               2 (==)
             10 RETURN_VALUE


  # 1 in ([] == False)
  1           0 LOAD_CONST               0 (1)
              2 BUILD_LIST               0
              4 LOAD_CONST               1 (False)
              6 COMPARE_OP               2 (==)
              8 COMPARE_OP               6 (in)
             10 RETURN_VALUE

I'm especially intrigued by the ROT_THREE, ROT_TWO and JUMP_IF_FALSE_OR_POP instructions.

DeepSpace
  • 78,697
  • 11
  • 109
  • 154
  • 5
    It's comparison chaining, `(1 in []) and ([] == False)`: https://docs.python.org/3/reference/expressions.html#comparisons. – jonrsharpe Jan 19 '21 at 19:58
  • 2
    I'm out of votes, but dupe: https://stackoverflow.com/q/40987185/3001761 – jonrsharpe Jan 19 '21 at 19:59
  • @jonrsharpe ahh of course! that explains the `JUMP` (the chain is shortcircuited from left to right). Didn't expect to be able to use chaining with `in`. Thanks! and don't worry, will gladly mark this as a dupe on your behalf (edit: someone beat me to it). – DeepSpace Jan 19 '21 at 20:02
  • 3
    @DeepSpace yeah, it is really not intuitive to me that `in` counts as a comparison operator, but I guess it makes sense. But still in my mind, *comparison* operators should just be <, >, ==, >=, <=, and != – juanpa.arrivillaga Jan 19 '21 at 20:04
  • @juanpa.arrivillaga Yeah.. I guess that "learning a new thing every day" is not a cliche – DeepSpace Jan 19 '21 at 20:06

0 Answers0