2

I tried assigning three expressions in Python but I'm an unexpected result.

Let's begin with simple swaps. You probably know the result of this assignment:

A = [10, 11, 12]
p = 0
A[p + 1], A[p] = A[p], A[p + 1]    # <--
print(A)

The result is (as expected):

[11, 10, 12]

Now I wanted to be a little more daring, so tried this assignment:

A = [10, 11, 12]
p = 0
p, A[p + 1], A[p] = p + 1, A[p], A[p + 1]   # <--
print(A)

I thought that the result would be:

[10, 12, 11]

However, the result was:

[10, 11, 10]

Which is unexpected!

I read Python documentation regarding assignments:

Although the definition of assignment implies that overlaps between the left-hand side and the right-hand side are ‘simultaneous’ (for example a, b = b, a swaps two variables), overlaps within the collection of assigned-to variables occur left-to-right, sometimes resulting in confusion. For instance, the following program prints [0, 2]:

x = [0, 1]
i = 0
i, x[i] = 1, 2         # i is updated, then x[i] is updated
print(x)

I did not get similar results for my swap. I don't understand the logic behind my swap. What's going on?

3
  • 1
    The output you got was the output you were supposed to get! Commented Apr 2, 2019 at 15:02
  • 1
    Not directly related to your question, but docs.python.org/2.0/ref/assignment.html is considerably out of date. Refer to docs.python.org/3/reference/… or docs.python.org/2.7/reference/… for 3.X and 2.7 documentation respectively. Commented Apr 2, 2019 at 15:03
  • 1
    This is somewhat similar to writing C code like x[i++]=i++. Don't do it; even if the behavior is well defined, it may not be especially clear. Increment p, then perform the swap. Commented Apr 2, 2019 at 15:19

1 Answer 1

4

You can see it as a shorthand for consecutive assignments from left to right using temporary variables:

p, A[p + 1], A[p] = p + 1, A[p], A[p + 1]

is equivalent to

temp1  = p + 1  # 1
temp2  = A[p]   # 10  (A[0])
temp3  = A[p+1] # 11  (A[1])
p      = temp1   # p    = 1
A[p+1] = temp2   # A[2] = 10
A[p]   = temp3   # A[1] = 11

so A = [10,11,10]

If you placed p at the end of the list, you probably would get closer to your expected result:

A[p + 1], A[p], p = A[p], A[p + 1], p + 1

A is now [11,10,12]
P is now 1

In other words, post-increment is possible but pre-increment will not work in this kind of scenario (where the pre-incremented index is used in the source data)

You could do it by manually computing the offset in the source data but that would be somewhat counter-intuitive:

p, A[p+1], A[p] = p+1, A[p+1], A[p+2]
Sign up to request clarification or add additional context in comments.

4 Comments

Relevant documentation for whom it may interest: docs.python.org/3/reference/expressions.html#evaluation-order
Thanks for editing my question and thank for your relevant document. @TrebledJ
thanks for great answer.I like you. Nice answer. Is it possible to explain those two things: 1. pre-incerment and post-incerment 2.counter-intuitive @alain-t
Pre-increment is when you increase the index (p) before using it. post-increment is when you increase the index after using it. What I felt is counter intuitive is that , in my last (pre-increment) example, the assignment's left side assumes a value of p that has been incremented but the right side of the assignment indexes the list with p before it is incremented (despite having p+1 appear before the A[..] source data).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.