Ответ 1
Мои извинения за длину этого сообщения, но я решил выбрать полноту.
Как только вы знаете несколько основных правил, их не сложно обобщить. Я сделаю все возможное, чтобы объяснить несколько примеров. Поскольку вы говорите об оценке этих "вручную", я предложу несколько простых правил замены. В принципе, вам может быть легче понять выражение, если все итерации отформатированы таким же образом.
Только для распаковки в правой части =
(т.е. для rvalues) действуют следующие подстановки:
'XY' -> ('X', 'Y')
['X', 'Y'] -> ('X', 'Y')
Если вы обнаружите, что значение не распаковывается, вы отмените замену. (Подробнее см. Ниже).
Кроме того, когда вы видите "голые" запятые, притворяйтесь там кортежем верхнего уровня. Сделайте это как с левой, так и с правой стороны (то есть для lvalues и rvalues):
'X', 'Y' -> ('X', 'Y')
a, b -> (a, b)
С учетом этих простых правил, вот несколько примеров:
(a,b), c = "XY", "Z" # a = 'X', b = 'Y', c = 'Z'
Применяя приведенные выше правила, мы преобразуем "XY"
в ('X', 'Y')
и покрываем голые запятые в parens:
((a, b), c) = (('X', 'Y'), 'Z')
Визуальная переписка здесь делает достаточно очевидным, как работает присвоение.
Вот ошибочный пример:
(a,b), c = "XYZ"
Следуя приведенным выше правилам замены, мы получаем следующее:
((a, b), c) = ('X', 'Y', 'Z')
Это явно ошибочно; вложенные структуры не совпадают. Теперь посмотрим, как это работает для немного более сложного примера:
(a,b), c, = [1,2],'this' # a = '1', b = '2', c = 'this'
Применяя приведенные выше правила, получим
((a, b), c) = ((1, 2), ('t', 'h', 'i', 's'))
Но теперь из структуры ясно, что 'this'
не распаковывается, а назначается непосредственно c
. Поэтому мы отменя замену.
((a, b), c) = ((1, 2), 'this')
Теперь посмотрим, что произойдет, когда мы завершим c
в кортеж:
(a,b), (c,) = [1,2],'this' # ERROR -- too many values to unpack
становится
((a, b), (c,)) = ((1, 2), ('t', 'h', 'i', 's'))
Опять же, ошибка очевидна. c
уже не голая переменная, а переменная внутри последовательности, поэтому соответствующая последовательность справа распаковывается в (c,)
. Но последовательности имеют разную длину, поэтому есть ошибка.
Теперь для расширенной распаковки с помощью оператора *
. Это немного сложнее, но все еще довольно просто. Переменной, предшествующей *
, становится список, который содержит любые элементы из соответствующей последовательности, которые не назначаются именам переменных. Начиная с довольно простого примера:
a, *b, c = "X...Y" # a = 'X', b = ['.','.','.'], c = 'Y'
Это становится
(a, *b, c) = ('X', '.', '.', '.', 'Y')
Самый простой способ проанализировать это - это работать с концов. 'X'
присваивается a
, а 'Y'
присваивается c
. Остальные значения в последовательности помещаются в список и назначаются b
.
Lvalues, такие как (*a, b)
и (a, *b)
, являются только особыми случаями выше. У вас не может быть двух операторов *
внутри одной последовательности lvalue, потому что это будет неоднозначно. Где значения будут выглядеть примерно так: (a, *b, *c, d)
- in b
или c
? Я рассмотрю вложенный случай в одно мгновение.
*a = 1 # ERROR -- target must be in a list or tuple
Здесь ошибка довольно понятна. Цель (*a
) должна быть в кортеже.
*a, = (1,2) # a = [1,2]
Это работает, потому что там голая запятая. Применение правил...
(*a,) = (1, 2)
Так как нет переменных, кроме *a
, *a
вырывает все значения в последовательности rvalue. Что, если вы замените (1, 2)
на одно значение?
*a, = 1 # ERROR -- 'int' object is not iterable
становится
(*a,) = 1
Опять же, ошибка здесь не требует пояснений. Вы не можете распаковать то, что не является последовательностью, а *a
нужно что-то распаковать. Поэтому мы помещаем его в последовательность
*a, = [1] # a = [1]
Что эквивалентно
(*a,) = (1,)
Наконец, это общая точка смущения: (1)
совпадает с 1
- вам нужна запятая, чтобы отличить кортеж от арифметического утверждения.
*a, = (1) # ERROR -- 'int' object is not
Теперь для гнездования. На самом деле этот пример не был в вашем разделе "NESTED"; возможно, вы не понимали, что он вложен?
(a,b), *c = 'XY', 2, 3 # a = 'X', b = 'Y', c = [2,3]
становится
((a, b), *c) = (('X', 'Y'), 2, 3)
Первое значение в корте верхнего уровня назначается, а оставшиеся значения в корте верхнего уровня (2
и 3
) присваиваются c
- как и следовало ожидать.
(a,b),c = 1,2,3 # ERROR -- too many values to unpack
*(a,b), c = 1,2,3 # a = 1, b = 2, c = 3
Я уже объяснил, почему первая строка вызывает ошибку. Вторая строка глупа, но вот почему она работает:
(*(a, b), c) = (1, 2, 3)
Как объяснялось ранее, мы работаем с концами. 3
присваивается c
, а затем остальные значения назначаются переменной с предшествующим ей *
, в данном случае (a, b)
. Таким образом, что эквивалентно (a, b) = (1, 2)
, который работает, потому что есть правильное количество элементов. Я не могу думать о какой-либо причине, которая когда-либо появлялась в рабочем коде. Аналогично,
*(a, *b), c = 'this' # a = 't', b = ['h', 'i'], c = 's'
становится
(*(a, *b), c) = ('t', 'h', 'i', 's')
Работа с концами, 's'
назначается c
, а ('t', 'h', 'i')
назначается (a, *b)
. Работая снова с концов, 't'
назначается a
, а ('h', 'i')
назначается b как список. Это еще один глупый пример, который никогда не должен появляться в рабочем коде.