4

Is it possible to pass a slice of a list into a function and modify the list via the slice?

This doesn't seem to work:

def foo(a_list):
  a_list[0]='abc'

x=[1,2,3,4]
foo(x[0:2])

I want x to now be x=['abc',2,3,4]

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
LoveToCode
  • 53
  • 5

5 Answers5

4

No. A "list slice" in the sense you describe is nothing but a new list. When you do x[0:2], the resulting list does not "know" that it was created as a slice of another list. It's just a new list.

What you could do is pass in the slice object itself, separately from the list:

def foo(a_list, a_slice):
  a_list[a_slice]='abc'

>>> foo(x, slice(0, 2))
>>> x
['a', 'b', 'c', 3, 4]
BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • If a list slice is a new list how come I can modify a list by modifying its slice? For example, `l = [1, 2, 3]; l[0] = 100` will turn the first element of the list into 100. – Heisenberg May 02 '20 at 05:09
  • 1
    @Heisenberg: You should ask a separate question if you have a separate question. – BrenBarn May 03 '20 at 06:09
  • I asked a new question here https://stackoverflow.com/questions/61580214/if-python-slice-copy-the-reference-why-cant-i-use-it-to-modify-the-original-li – Heisenberg May 03 '20 at 19:12
3

No! Slices create copies of lists (see the documentation). You can do this:

>>> x = [1, 2, 3, 4]
>>> x[1:3] = [7, 8, 9]
>>> X
[1, 7, 8, 9, 4]

But, when you get a new list from a slicing operation, it's a copy, and thus changes to it won't affect the original:

>>> x = [1, 2, 3, 4]
>>> y = x[1:3]
>>> y[0] = 5
>>> y
[5, 3]
>>> x
[1, 2, 3, 4]
brenns10
  • 3,109
  • 3
  • 22
  • 24
2
def foo(a_list):
  a_list[0]='abc'
  return a_list

x=[1,2,3,4]
foo(x) #it returns x=['abc',2,3,4]
Mir Ilias
  • 475
  • 3
  • 9
2

Assumably you're trying to pass in x[0:2], rather than x[0,2], but the reason it doesn't work is because when you create a slice you are creating a subarray copy of x.

You are not operating on the same instance of that array, what you are doing is passing an entirely new array. Passing in 'x' alone would work, but passing in x[0:2] would not unless you specifically wrote it as x[0:2] = foo(x[0:2]) and had foo() return a_list.

Noi Sek
  • 544
  • 8
  • 22
2

As brenns10 explained, slices create a copy (even in python 3.0) of your origional data.

You could do something like the following:

def foo(x):
  x[0] = 'abc'
  return x

x = [0, 1, 2, 3]
x[0:2] = foo(x[0:2])  # x = ['abc', 1, 2, 3]

While this gives you the desired outcome, it doesn't exactly work as you would want. This could be problematic if needing to perform large slices as you'd have to perform a lot of copying.

Timothy Murphy
  • 1,322
  • 8
  • 16