Slice Assignment with a String in a List
Question:
I did quite a bit of perusing, but I don’t have a definite answer for the concept that I’m trying to understand.
In Python, if I take a list, such as:
L1=['muffins', 'brownies','cookies']
And then attempted to replace the first pointer to an object in the list, namely ‘muffins’ by using the code:
L1[0:1] = 'cake'
I would get a list L1:
['c', 'a', 'k', 'e', 'brownies', 'cookies']
Yet if I took the same list and performed the operation (now with the 4 elements from the string cake):
L1[0:4] = ['cake'] # presumably, it's now passing the string cake within a list? (it passed into the modified list shown above)
I get the output I initially desired:
['cake', 'brownies', 'cookies']
Can anyone explain why that is, exactly?
I’m assuming that when I take cake initially without it being in a “list”, it breaks the string into its individual characters to be stored as references to those characters as opposed to a single reference to a string…
But I’m not entirely sure.
Answers:
If you specify a slice, the righthand side is presumed to be a list/tuple (actually, any iterable – but watch out for generators that produce an indefinite number of values).
To replace an item in a list, use:
my_list[0] = "cake"
(You could also do
my_list[0:1] = ["cake"]
if you really want to use a list slice.
See also:
slice assignment
Two important points:
- Slice assignment takes an iterable on the right-hand side, and replaces the elements of the slice with the objects produced by the iterable.
- In Python, strings are iterable: iterating over a string yields its characters.
Thus
L1[0:1] = 'cake'
replaces the first element of L1
with the individual characters of 'cake'
.
To replace the first element with the string 'cake'
, simply write:
L1[0] = 'cake'
or, using the slice assignment syntax:
L1[0:1] = ['cake']
Think of strings as being a sequence container that stores characters. When you try to do assignments that way, it adds each item in the character sequence to the list. By wrapping “cake” in its own 1-element list first (let’s call it L2), you’re instead adding each element of L2 to L1 — it does not recursively split up sequence containers beyond the outermost sequence.
L1 = ['muffins', 'brownies','cookies']
L2 = ['cake']
L1[0:1] = L2
print L1
['cake', 'brownies', 'cookies']
This is also true for other nested sequence objects. Try experimenting with more nested sequence objects like this:
L3 = [['pie', 'eclairs'], ['bacon', 'chocolate']]
L1[0:1] = L3
print L1
[['pie', 'eclairs'], ['bacon', 'chocolate'], 'brownies', 'cookies']
It’s also worth noting that if you don’t care about order/positioning in the list, you can use append()
and not have to worry about your string getting split up:
L1 = ['muffins', 'brownies','cookies']
L1.append('cake')
print L1
['muffins', 'brownies', 'cookies', 'cake']
I did quite a bit of perusing, but I don’t have a definite answer for the concept that I’m trying to understand.
In Python, if I take a list, such as:
L1=['muffins', 'brownies','cookies']
And then attempted to replace the first pointer to an object in the list, namely ‘muffins’ by using the code:
L1[0:1] = 'cake'
I would get a list L1:
['c', 'a', 'k', 'e', 'brownies', 'cookies']
Yet if I took the same list and performed the operation (now with the 4 elements from the string cake):
L1[0:4] = ['cake'] # presumably, it's now passing the string cake within a list? (it passed into the modified list shown above)
I get the output I initially desired:
['cake', 'brownies', 'cookies']
Can anyone explain why that is, exactly?
I’m assuming that when I take cake initially without it being in a “list”, it breaks the string into its individual characters to be stored as references to those characters as opposed to a single reference to a string…
But I’m not entirely sure.
If you specify a slice, the righthand side is presumed to be a list/tuple (actually, any iterable – but watch out for generators that produce an indefinite number of values).
To replace an item in a list, use:
my_list[0] = "cake"
(You could also do
my_list[0:1] = ["cake"]
if you really want to use a list slice.
See also:
slice assignment
Two important points:
- Slice assignment takes an iterable on the right-hand side, and replaces the elements of the slice with the objects produced by the iterable.
- In Python, strings are iterable: iterating over a string yields its characters.
Thus
L1[0:1] = 'cake'
replaces the first element of L1
with the individual characters of 'cake'
.
To replace the first element with the string 'cake'
, simply write:
L1[0] = 'cake'
or, using the slice assignment syntax:
L1[0:1] = ['cake']
Think of strings as being a sequence container that stores characters. When you try to do assignments that way, it adds each item in the character sequence to the list. By wrapping “cake” in its own 1-element list first (let’s call it L2), you’re instead adding each element of L2 to L1 — it does not recursively split up sequence containers beyond the outermost sequence.
L1 = ['muffins', 'brownies','cookies']
L2 = ['cake']
L1[0:1] = L2
print L1
['cake', 'brownies', 'cookies']
This is also true for other nested sequence objects. Try experimenting with more nested sequence objects like this:
L3 = [['pie', 'eclairs'], ['bacon', 'chocolate']]
L1[0:1] = L3
print L1
[['pie', 'eclairs'], ['bacon', 'chocolate'], 'brownies', 'cookies']
It’s also worth noting that if you don’t care about order/positioning in the list, you can use append()
and not have to worry about your string getting split up:
L1 = ['muffins', 'brownies','cookies']
L1.append('cake')
print L1
['muffins', 'brownies', 'cookies', 'cake']