How to use list[list.index('')] queries in python
Question: I tried the following code in python IDLE. But I didn't seem to find the
elements swapped.

    
    
    >>> a = [1,2,3,4,5,6,7]
    >>> if(a.index(2)<a.index(4)):
    ...     a[a.index(2)],a[a.index(4)] = a[a.index(4)],a[a.index(2)]
    

According to the code, It should reverse the positions of 2 and 4. Correct me
If I am wrong.


Answer: The assignment list expressions are evaluated left-to-right _while assigning_.

Here is what happens:

  * The right-hand-expression is evaluated to yield `(4, 2)`
  * `a[a.index(2)]` is evaluated to assign `4` to, `a[2]` is altered, the list becomes `[1, 4, 3, 4, 5, 6, 7]`
  * `a[a.index(4)]` is evaluated to assign `2` to, `a[2]` is altered _again_ because that is now the first position `4` is back to `[1, 2, 3, 4, 5, 6, 7]`.

You can see this in the disassembled Python byte code:

    
    
    >>> def foo():
    ...     a = [1,2,3,4,5,6,7]
    ...     a[a.index(2)],a[a.index(4)] = a[a.index(4)],a[a.index(2)]
    ... 
    >>> import dis
    >>> dis.dis(foo)
      2           0 LOAD_CONST               1 (1)
                  3 LOAD_CONST               2 (2)
                  6 LOAD_CONST               3 (3)
                  9 LOAD_CONST               4 (4)
                 12 LOAD_CONST               5 (5)
                 15 LOAD_CONST               6 (6)
                 18 LOAD_CONST               7 (7)
                 21 BUILD_LIST               7
                 24 STORE_FAST               0 (a)
    
      3          27 LOAD_FAST                0 (a)
                 30 LOAD_FAST                0 (a)
                 33 LOAD_ATTR                0 (index)
                 36 LOAD_CONST               4 (4)
                 39 CALL_FUNCTION            1
                 42 BINARY_SUBSCR       
                 43 LOAD_FAST                0 (a)
                 46 LOAD_FAST                0 (a)
                 49 LOAD_ATTR                0 (index)
                 52 LOAD_CONST               2 (2)
                 55 CALL_FUNCTION            1
                 58 BINARY_SUBSCR       
                 59 ROT_TWO             
                 60 LOAD_FAST                0 (a)
                 63 LOAD_FAST                0 (a)
                 66 LOAD_ATTR                0 (index)
                 69 LOAD_CONST               2 (2)
                 72 CALL_FUNCTION            1
                 75 STORE_SUBSCR        
                 76 LOAD_FAST                0 (a)
                 79 LOAD_FAST                0 (a)
                 82 LOAD_ATTR                0 (index)
                 85 LOAD_CONST               4 (4)
                 88 CALL_FUNCTION            1
                 91 STORE_SUBSCR        
                 92 LOAD_CONST               0 (None)
                 95 RETURN_VALUE        
    

By instruction index 59, Python has evaluated the right-hand-side expression;
next up are the assignments. You can see that `a.index(2)` (63-72) is
evaluated first, then the `STORE_SUBSCR` stores the `4`, and only _then_
`a.index(4)` is evaluated (instructions 79-85).

The workaround is to call `.index()` _once_ for each value, and storing the
indices in variables:

    
    
    index_two, index_four = a.index(2), a.index(4)
    if index_two < index_four:
        a[index_two], a[index_four] = a[index_four], a[index_two]
    

