#python #python-3.x #variable-assignment
#python #python-3.x #переменная-присвоение #переменная-назначение
Вопрос:
Я попытался назначить три выражения в Python, но я получил неожиданный результат.
Давайте начнем с простых замен. Вы, вероятно, знаете результат этого назначения:
A = [10, 11, 12]
p = 0
A[p 1], A[p] = A[p], A[p 1] # <--
print(A)
Результат (как и ожидалось):
[11, 10, 12]
Теперь я хотел быть немного более смелым, поэтому попробовал это назначение:
A = [10, 11, 12]
p = 0
p, A[p 1], A[p] = p 1, A[p], A[p 1] # <--
print(A)
Я думал, что результатом будет:
[10, 12, 11]
Однако результат был:
[10, 11, 10]
Что неожиданно!
Я прочитал документацию по Python, касающуюся назначений:
Хотя определение присваивания подразумевает, что совпадения между левой и правой сторонами являются ‘одновременными’ (например, a, b = b, a меняет местами две переменные), совпадения в коллекции присвоенных переменных происходят слева направо, иногда приводя к путанице. Например, следующая программа выводит [0, 2]:
x = [0, 1] i = 0 i, x[i] = 1, 2 # i is updated, then x[i] is updated print(x)
Я не получил аналогичных результатов для своего swap. Я не понимаю логику, стоящую за моим обменом. Что происходит?
Комментарии:
1. Полученный вами результат был тем результатом, который вы должны были получить!
2. Не имеет прямого отношения к вашему вопросу, но docs.python.org/2.0/ref/assignment.html значительно устарел. Обратитесь к docs.python.org/3/reference /… или docs.python.org/2.7/reference /… для документации 3.X и 2.7 соответственно.
3. Это несколько похоже на написание кода на C, подобного
x[i ]=i
. Не делайте этого; даже если поведение четко определено, оно может быть не особенно понятным. Увеличьте значениеp
, затем выполните замену.
Ответ №1:
Вы можете рассматривать это как сокращение для последовательных назначений слева направо с использованием временных переменных:
p, A[p 1], A[p] = p 1, A[p], A[p 1]
эквивалентно
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
итак A = [10,11,10]
Если вы разместите p
в конце списка, вы, вероятно, приблизитесь к ожидаемому результату:
A[p 1], A[p], p = A[p], A[p 1], p 1
A is now [11,10,12]
P is now 1
Другими словами, последующее увеличение возможно, но предварительное увеличение не будет работать в сценарии такого типа (где в исходных данных используется предварительно увеличенный индекс)
Вы могли бы сделать это, вручную вычисляя смещение в исходных данных, но это было бы несколько нелогично:
p, A[p 1], A[p] = p 1, A[p 1], A[p 2]
Комментарии:
1. Соответствующая документация, для кого это может представлять интерес: docs.python.org/3/reference/expressions.html#evaluation-order
2. Спасибо за редактирование моего вопроса и благодарю за ваш соответствующий документ. @TrebledJ
3. спасибо за отличный ответ. Ты мне нравишься. Хороший ответ. Возможно ли объяснить эти две вещи: 1. предварительное включение и последующее включение 2.нелогичный @alain-t
4. Предварительное увеличение — это когда вы увеличиваете индекс (p) перед его использованием. постинкремент — это когда вы увеличиваете индекс после его использования. Что мне показалось нелогичным, так это то, что в моем последнем примере (с предварительным приращением) левая сторона присваивания принимает значение p, которое было увеличено, но правая сторона присваивания индексирует список с помощью p перед его увеличением (несмотря на то, что p 1 отображается перед исходными данными A [..]).