Strange behavior of Python 'is' operator if combined with 'in'
Question: 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)


Answer: 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:
<http://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)

