Назначение среза с пустым списком - почему?

1

у меня вопрос. Я боюсь, что это может быть очевидно для вас, но я не совсем понимаю это в данный момент.

Я только что прочитал о назначении slice и о том, как назначение пустого списка работает как элемент delete, fe:

>> L=['a','b','c','d']
>> L[2:3] = []
>> L
['a', 'b', 'd']

Но вот мой вопрос - не логичнее ли ожидать этого вывода?

['a', 'b', [], 'd']

Я знаю, что вывод выше будет правдой, если мой код будет выглядеть так:

>> L=['a','b','c','d']
>> L[2:3] = [[]]
>> L

но почему он построил этот путь, а не как fe:

>> L=['a','b','c','d']
>> L[2:3] = None
>> L

Это выглядит слишком сложным для меня, потому что я ожидаю, что когда я сделаю slice-присваивание, я не ожидаю, что в этой ситуации он изменит длину моего списка, или, может быть, я хочу просто удалить срез и инициировать пустой список на в то же время.

EDIT: Я не знаю, был ли я достаточно ясным - я не понимал, почему - при выполнении назначения slice - интерпретатор python удаляет элемент в списке вместо изменения этого элемента для пустого списка.

  • 0
    В этом случае нарезка изменяет длину списка - это удаление данных из списка. Если вы не хотите, чтобы длина вашего списка изменялась, поместите туда значение, например пустую строку: L [2: 3] = ''. Тогда список будет ['a', 'b', '', 'd']
  • 0
    Почему вставка пустого списка имеет смысл? Почему не пустой кортеж, не пустой диктант или None? Назначение среза ожидает повторяемость . Ваш повторяемый пустой.
Теги:
slice

3 ответа

1
Лучший ответ

Я думаю, что путаница исходит из того факта, что вы действительно нарезаете и не индексируете. Заметим:

>>> L = ['a','b','c','d']
>>> L[2] = []
>>> L
['a', 'b', [], 'd']

Заметим, что L[2:3] "идентичен" L[2] в отношении диапазона 2-3, всего 2 (поскольку нарезка не включена). Однако нарезка и индексирование - это два разных поведения, поскольку нарезка может изменить длину списка, тогда как индексирование просто изменяет существующий элемент.


Причина, по которой пустой список работает таким образом, связана с тем, как работает назначение среза. Когда вы назначаете срез, python распаковывает то, что вы ему даете, и сохраняет свои результаты в индексах. Заметим:

>>> L = ['a', 'b', 'c', 'd']
>>> L[2:4] = 'e'
>>> L
['a', 'b', 'e']
>>> L = ['a', 'b', 'c', 'd']
>>> L[2:4] = 'efgh'
>>> L
['a', 'b', 'e', 'f', 'g', 'h']

Поведение L[2:4] = 'e' и L[2:4] = ['e'] одно и то же в python из-за поведения строк в Python: они могут быть перезаписаны и, следовательно, распакованы.

Поэтому, когда вы помещаете L[2:4] = [], он распаковывает все элементы [] и присваивает их содержимое индексам 2 и 3. Конечно, поскольку нет элементов, он не присваивает их ничто (примечание: отличается от None или "" - буквально ничто) и, следовательно, удаляется.

  • 0
    Спасибо за быстрый ответ! Я понимаю эту разницу. Вещь, которую я не понимаю, заключается в том, почему было выбрано использование пустого списка в качестве «удаления» в этом случае нарезки.
0

Когда вы назначаете фрагмент списка, аргумент правой руки должен быть итерируемым объектом. Этот итеративный файл распаковывается, а значения заменяют значения в нарезанной части исходной последовательности. Для срезов с размером шага один (или отрицательный) это работает независимо от того, имеют ли срез и итерабельность одинаковый размер.

Рассмотрим следующие примеры:

a = [1, 2, 3, 4]
a[1:3] = [5, 6, 7]
print(a) # prints [1, 5, 6, 7, 4]

a = [1, 2, 3, 4]
a[1:3] = [5]
print(a) # prints [1, 5, 4]

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

Однако это не стандартный способ удаления элементов. Обычный способ - использовать инструкцию del. Назначение среза, такое a[1:3] = [] в точности эквивалентно del a[1:3], но последнее предпочтительнее, поскольку оно гораздо более четко указывает на то, что ожидается.

  • 0
    Вы мне тоже помогли - я не знал, что это может быть любой итеративный объект, а не только список :)
0

Нарезка не меняет длину, присваивание делает. Экстракты нарезки. Индексирование выбирает один элемент. Индексирование не изменяет длину, присваивание делает.

>>> L = ['a','b','c','d']
>>> L[2:4]   
['c', 'd'] # that the extraction of a slice.
>>> L[2:4] = []  # that assignment using a slice and an empty list as operands.  
>>> L
['a', 'b'] 
>>>L[1]
'b'   # that the selection of an index 
>>>L[1] = 0
>>>L
['a', 0] #that assignment using an index and integer as operands. 

Таким образом, извлечение из списка строк должно по-прежнему оставлять вас со списком строк, а не строк и пустых списков - это будет изменение типа.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню