Skip to content Skip to sidebar Skip to footer

Python Tuple Assignment Involving List Index Failed

Say the list s = [1, 2] and I want to use tuple assignments to edit the list. Why it is fine to do s[s[0]], s[0] = s[0], s[s[0]] # s == [2, 1] but not s[0], s[s[0]] = s[s[0]], s[

Solution 1:

A good explanation of what is happening under the hood can be found here. Essentially when you have multiple assignments anything to the right of the = will be fully evaluated first.

Let’s take your first example and walk through what is happening.

s[s[0]], s[0] = s[0], s[s[0]] # s == [2, 1]

This is equivalent to the following where temp values store the evaluated right hand sides

# assigns right hand side to temp variables

temp1 = s[0]    # 1
temp2 = s[s[0]] # 2# then assign those temp variables to the left-hand side

s[s[0]] = temp1 # s[1] = 1 —-> s= [1, 1]
s[0] = temp2    # s[0] = 2 —-> s = [2, 1]

In the case you get an index error the following happens...

# assigns right hand side to temp variables

temp1 = s[s[0]] # 2
temp2 = s[0]    # 1# then assign those temp variables to the left-hand side

s[0] = temp1 # s[0] = 2 —-> s= [2, 1]
s[s[0]] = temp2  # s[2] -> Index error (highest index of s is 1)

Solution 2:

When you do s[a], s[b] = s[b], s[a], the right side of the = is evaluated completely before assigning the values back to the list, which is why one-line-swaps work in Python. However, it seems like the left side of the = is not evaluated all at once, but one after another. Thus, for s[0], s[s[0]] = s[s[0]], s[0], the s[0] in s[s[0]] on the left side is evaluated after s[0] was assigned a new value.

This can be verified by wrapping the indices into a function that prints them before returning them:

>>> s = [1, 2]
>>> f = lambda i, j: print("get", i, j) or j
>>> s[f("a",0)], s[f("b",s[f("c",0)])] = s[f("d", s[f("e", 0)])], s[f("f", 0)]
get e 0get d 1get f 0get a 0get c 0get b 2<-- updated to 2 before s[0] was evaluated
Traceback (most recent calllast):
  File "<stdin>", line 1, in<module>
IndexError: list assignment index outofrange

In other words, the expression s[0], s[s[0]] = s[s[0]], s[0] seems to be roughly equivalent to the following, i.e. the indices used in the LHS are not evaluated all at once before being assigned new values:

tmp = (s[s[0]], s[0])
s[0] = tmp[0]
s[s[0]] = tmp[1]

Solution 3:

lists are assigned by reference, meaning changing the content of the source will result in changing the target assignment.

list = [1,2]
a = [4]
list.append(a) # value is 4

a[0] = 5 # also changes target "list"
print (list) # will output [1,2,[5]]

Post a Comment for "Python Tuple Assignment Involving List Index Failed"