Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behavior of Python 'is' operator if combined with 'in' [duplicate]

Tags:

python

How does Python interpret "'a' in 'abc' is True"? I was trying to evaluate the following two expressions:

>>> 'a' in 'abc' is True:
False
>>> ('a' in 'abc') is True:
True

(I know "is" keyword shouldn't generally be used to compare to True, this is just an example)

like image 389
user2989360 Avatar asked Nov 14 '13 21:11

user2989360


1 Answers

Interesting question!

Here's the bytecode from 'a' in 'abc' is True:

>>> import dis
>>> dis.disassemble((lambda: 'a' in 'abc' is True).func_code)
2           0 LOAD_CONST               1 ('a')   # stack: 'a'
            3 LOAD_CONST               2 ('abc') # stack: 'a' 'abc'
            6 DUP_TOP                            # stack: 'a' 'abc' 'abc'
            7 ROT_THREE                          # stack: 'abc' 'a' 'abc'
            8 COMPARE_OP               6 (in)    # stack: 'abc' True
           11 JUMP_IF_FALSE_OR_POP    21         # stack: 'abc'
           14 LOAD_GLOBAL              0 (True)  # stack: 'abc' True
           17 COMPARE_OP               8 (is)    # stack: False
           20 RETURN_VALUE        
      >>   21 ROT_TWO
           22 POP_TOP
           23 RETURN_VALUE                      

And compare with that from ('a' in 'abc') is True:

>>> import dis
>>> dis.disassemble((lambda: ('a' in 'abc') is True).func_code)
1           0 LOAD_CONST               1 ('a')   # stack: 'a'
            3 LOAD_CONST               2 ('abc') # stack: 'a' 'abc'
            6 COMPARE_OP               6 (in)    # stack: True
            9 LOAD_GLOBAL              0 (True)
           12 COMPARE_OP               8 (is)
           15 RETURN_VALUE        

So it seems like the expression 'a' in 'abc' is True evaluates as roughly:

>>> 'a' in 'abc' and 'abc' is True

It seems like this is a result of operator chaining: https://stackoverflow.com/a/19751586/71522 — the same magic which makes 1 < 5 < 10 work properly.

Very interesting!

(Note: this was done with CPython 2.7.2)

like image 69
David Wolever Avatar answered Oct 31 '22 17:10

David Wolever