In this question there is a code that in a simplified form can be written as:

>>> '1' in '111' == True False 

Why it happens? After all, according to the table "Operator precedence" and in and == have the same priority and must be executed from left to right.

Those. It is logical to assume that this construction is equivalent:

 >>> ('1' in '111') == True True 

    2 answers 2

    We will use the dis module to analyze bytecode.

     import dis dis.dis("'1' in '111' == True") 

    We get the following conclusion

     1 0 LOAD_CONST 0 ('1') 2 LOAD_CONST 1 ('111') 4 DUP_TOP 6 ROT_THREE 8 COMPARE_OP 6 (in) 10 JUMP_IF_FALSE_OR_POP 18 12 LOAD_CONST 2 (True) 14 COMPARE_OP 2 (==) 16 RETURN_VALUE >> 18 ROT_TWO 20 POP_TOP 22 RETURN_VALUE 

    The LOAD_CONST instruction loads constants on the stack, DUP_TOP duplicates the value of the top of the stack and adds it to the stack, ROT_THREE raises 2 and 3 values ​​in the stack 1 position up, dropping the value of the top of the stack to position 3. Thus, before the in operation (offset 8) in the stack values ​​are stored ['111', '1', '111']. Further, there are two possible scenarios:

    • In the case of obtaining a false value, go to offset 18 with the stack [False, '111'], ROT_TWO swaps the top two values ​​of the stack, we get the stack ['111', False]. POP_TOP will remove '111' and RETURN_VALUE will return False.

    • If a true value is obtained after executing LOAD_CONST at offset 12, the stack will contain the following values ​​[True, '111']. Next, the operation compares the values ​​of True and '111', the result of which is pushed onto the stack and then returned.

    It turns out that the result of executing the expression '1' in '111' == True will be equal to the result of executing '1' in '111' and '111' == True

    It looks like this construction is perceived as "chained comparison" like:

     a < b <= c 

    which is equivalent to

     a < b and b <= c 

    those.

     '1' in '111' == True 

    will be processed as:

     '1' in '111' and '111' == True 

    check the guess:

     >>> '1' in '111' == '111' True 
    • one
      can be on ast look - jfs
    • 2
      compare ast.dump(ast.parse("1 < 2 <= 3", 'eval').body[0]) and ast.dump(ast.parse("1 in 2 == 3", 'eval').body[0]) - jfs
    • Thanks, looks convincing! Why not make an answer? - MaxU
    • four
      I'll wait, I'm not in a hurry;) Surely someone can use the example of parsing an expression using ast - MaxU
    • one
      it’s a pity that @jfs never got around to writing an answer: ( - Maximmka