Python Не удалось присвоить кортеж с использованием индекса списка - PullRequest
1 голос
/ 06 августа 2020

Произнесите список

s = [1, 2]

, и я хочу использовать назначения кортежей для редактирования списка. Почему можно делать

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

, но нельзя

s[0], s[s[0]] = s[s[0]], s[0] # get error, index out of range

Ответы [ 3 ]

2 голосов
/ 06 августа 2020

Хорошее объяснение того, что происходит под капотом, можно найти здесь . По сути, когда у вас есть несколько назначений, все, что справа от =, будет полностью оценено первым.

Давайте возьмем ваш первый пример и рассмотрим, что происходит.

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

Это эквивалентно следующему, где значения temp хранят оцененные правые части

# 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]

В случае, если вы получаете ошибку индекса, происходит следующее ...

# 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)
1 голос
/ 06 августа 2020

Когда вы выполняете s[a], s[b] = s[b], s[a], правая часть = полностью оценивается перед назначением значений обратно в список, поэтому однострочные замены работают в Python. Однако, похоже, что левая часть = - это не , вычисляемая сразу, а одна за другой. Таким образом, для s[0], s[s[0]] = s[s[0]], s[0] s[0] в s[s[0]] слева оценивается после того, как s[0] было присвоено новое значение.

Это можно проверить, заключив индексы в функцию, которая печатает перед их возвратом:

>>> 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 0
get d 1
get f 0
get a 0
get c 0
get b 2  <-- updated to 2 before s[0] was evaluated
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range

Другими словами, выражение s[0], s[s[0]] = s[s[0]], s[0] кажется примерно эквивалентным следующему, то есть индексы , используемые в LHS, вообще не оцениваются один раз перед присвоением новых значений:

tmp = (s[s[0]], s[0])
s[0] = tmp[0]
s[s[0]] = tmp[1]
0 голосов
/ 06 августа 2020

списки назначаются по ссылке, то есть изменение содержимого источника приведет к изменению целевого назначения.

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]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...