Вопрос-Ответ

How does assignment work with list slices?

Как присваивание работает с фрагментами списка?

В документах Python говорится, что при разделении списка возвращается новый список.
Теперь, если возвращается "новый" список, у меня возникают следующие вопросы, связанные с "Назначением фрагментам"

a = [1, 2, 3]
a[0:2] = [4, 5]
print a

Теперь результат будет следующим:

[4, 5, 3] 

  1. Как что-то, возвращающее что-то, может оказаться в левой части выражения?

  2. Да, я прочитал документы, и там говорится, что это возможно, теперь, поскольку фрагмент списка возвращает "новый" список, почему изменяется исходный список? Я не могу понять механику, стоящую за этим.

Переведено автоматически
Ответ 1

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

1) нарезка:

b = a[0:2]

Это создает копию фрагмента из a и присваивает его b.

2) назначение фрагментов:

a[0:2] = b

Это заменяет фрагмент a на содержимое b.

Хотя синтаксис похож (я полагаю, по дизайну!), это две разные операции.

Ответ 2

Когда вы указываете a в левой части = оператора, вы используете обычное присваивание в Python, которое изменяет имя a в текущем контексте, указывая на новое значение. Это не изменяет предыдущее значение, на которое a указывало.

Указывая a[0:2] в левой части = оператора, вы сообщаете Python, что хотите использовать присваивание фрагментов. Назначение фрагментов - это специальный синтаксис для списков, в котором вы можете вставлять, удалять или заменять содержимое из списка:

Вставка:

>>> a = [1, 2, 3]
>>> a[0:0] = [-3, -2, -1, 0]
>>> a
[-3, -2, -1, 0, 1, 2, 3]

Удаление:

>>> a
[-3, -2, -1, 0, 1, 2, 3]
>>> a[2:4] = []
>>> a
[-3, -2, 1, 2, 3]

Замена:

>>> a
[-3, -2, 1, 2, 3]
>>> a[:] = [1, 2, 3]
>>> a
[1, 2, 3]

Примечание:


Длина фрагмента может отличаться от длины назначенной последовательности, таким образом изменяя длину целевой последовательности, если целевая последовательность это позволяет. - Источник


Назначение фрагментов предоставляет функцию, аналогичную распаковке кортежей. Например, a[0:1] = [4, 5] эквивалентно:

# Tuple Unpacking
a[0], a[1] = [4, 5]

С помощью распаковки кортежей вы можете изменять непоследовательные списки:

>>> a
[4, 5, 3]
>>> a[-1], a[0] = [7, 3]
>>> a
[3, 5, 7]

Однако распаковка кортежа ограничивается заменой, поскольку вы не можете вставлять или удалять элементы.

До и после всех этих операций a это один и тот же точный список. Python просто предоставляет хороший синтаксический сахар для изменения списка на месте.

Ответ 3

Я сталкивался с тем же вопросом раньше, и он связан со спецификацией языка. Согласно assignment-statements,


  1. Если в левой части присваивания указано subscription, Python вызовет __setitem__ этот объект. a[i] = x эквивалентно a.__setitem__(i, x).


  2. Если левая часть присваивания является фрагментом, Python также вызовет __setitem__, но с другими аргументами: a[1:4]=[1,2,3] эквивалентно a.__setitem__(slice(1,4,None), [1,2,3])


Вот почему фрагмент списка в левой части '=' ведет себя по-другому.

Ответ 4

Выделяя фрагменты в левой части операции присваивания, вы указываете, каким элементам присваивать.

2023-06-19 16:07 python list