Назначение среза со строкой в ​​списке

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

В Python, если я беру список, например:

L1=['muffins', 'brownies','cookies']

И затем попытался заменить первый указатель на объект в списке, а именно "кексы", используя код:

L1[0:1] = 'cake'

Я бы получил список L1:

['c', 'a', 'k', 'e', 'brownies', 'cookies']

Но если я взял тот же список и выполнил операцию (теперь с 4 элементами из торта):

L1[0:4] = ['cake'] # presumably, it now passing the string cake within a list? (it passed into the modified list shown above)

Я получаю желаемый результат:

['cake', 'brownies', 'cookies']

Может ли кто-нибудь объяснить, почему это так? Я предполагаю, что когда я беру торт первоначально, не будучи в "списке", он разбивает строку на отдельные символы, которые будут храниться как ссылки на эти символы, а не на одну ссылку на строку...

Но я не совсем уверен.

Ответ 1

Два важных момента:

  • Назначение slice принимает итерацию с правой стороны и заменяет элементы среза на объекты, создаваемые итерабельным.
  • В Python строки итерабельны: итерация по строке приводит к ее символам.

Таким образом,

L1[0:1] = 'cake'

заменяет первый элемент L1 на отдельные символы 'cake'.

Чтобы заменить первый элемент строкой 'cake', просто напишите:

L1[0] = 'cake'

или, используя синтаксис назначения slice:

L1[0:1] = ['cake']

Ответ 2

Если вы указываете срез, правая сторона считается списком/кортежем (на самом деле, любой итерабельный - но следите за генераторами, которые производят неопределенное количество значений).

Чтобы заменить элемент в списке, используйте:

my_list[0] = "cake"

(Вы также можете сделать

my_list[0:1] = ["cake"]

если вы действительно хотите использовать фрагмент списка.

Вот пара других релевантных ссылок: назначение фрагментов больше назначения фрагментов

Ответ 3

Подумайте о строках как контейнере последовательности, в котором хранятся символы. Когда вы пытаетесь сделать назначения таким образом, он добавляет каждый элемент в последовательность символов в список. Сначала обернув "торт" в свой собственный 1-элементный список (позвоните ему L2), вместо этого вы добавляете каждый элемент L2 в L1 - он не рекурсивно разделяет контейнеры последовательностей за пределами самой внешней последовательности.

L1 = ['muffins', 'brownies','cookies']
L2 = ['cake']
L1[0:1] = L2
print L1
['cake', 'brownies', 'cookies']

Это также верно для других вложенных объектов последовательности. Попробуйте поэкспериментировать с более вложенными объектами последовательности, такими как:

L3 = [['pie', 'eclairs'], ['bacon', 'chocolate']]
L1[0:1] = L3
print L1
[['pie', 'eclairs'], ['bacon', 'chocolate'], 'brownies', 'cookies']

Также стоит отметить, что если вы не заботитесь о порядке/позиционировании в списке, вы можете использовать append() и не беспокоиться о том, что ваша строка будет разделена:

L1 = ['muffins', 'brownies','cookies']
L1.append('cake')
print L1
['muffins', 'brownies', 'cookies', 'cake']