Tony Ennis
Tony Ennis

Reputation: 12299

Why can't I change a list in a method?

I have a method that contains no loops. I pass a list into that method. I assign the list a new value per this snippet:

def do_paging(pageable_list):
    pageable_list = pageable_list[start:end]

In the calling code:

do_paging(source_list)

but it does not look like the source_list gets changed. If I return pageable_list from do_paging() everything is great. Are array arguments immutable?

I started returning the value because it's better. But I am surprised and would like to know what's going on.

EDIT - how could I have been programming Python for a year and not known this!

Upvotes: 1

Views: 193

Answers (3)

Alexander
Alexander

Reputation: 109546

I noticed this method below when I was recently reviewing code from Quantopian and had never it used before. Per the comment from @Steven_Rumbalski, this is assigning the slice back to the input variable pageable_list.

def do_paging(pageable_list, start, end):
    pageable_list[:] = pageable_list[start:end]

a = [1, 2, 3, 4, 5]

do_paging(a, 2, 4)

>>> a
[3, 4]

Upvotes: 3

timgeb
timgeb

Reputation: 78700

Slicing is creating a new list:

>>> a = [1,2,3]
>>> b = a[1:2]
>>> a is b
False

You are not mutating the original list:

>>> a
[1, 2, 3]

Furthermore, you are never doing anything with the list you assign the name pageable_list to in your do_paging function.

So the problems are a) you don't modify the original list and/or b) you don't return anything from your function. One way to make your code work is to create the slice and reassign the name pageable_list to the return value of your function, i.e.:

def do_paging(pageable_list, start, end):
    return pageable_list[start:end]

pageable_list = do_paging(pageable_list, start, end)

The function should probably take start and end arguments as well, looking for those in the global space is kind of ugly.

However, if all you need your function to do is the slicing, the function is not really useful, you could just use the line

pageable_list = pageable_list[start:end]

Upvotes: 5

deceze
deceze

Reputation: 522135

You're not changing "the list". You're assigning a new value to a local variable.

Mutating the list itself would work:

def do_paging(pageable_list):
    pageable_list.pop()

But the variable pageable_list is merely a local variable and assigning some new value to it does not modify the value which was previously assigned to it.

Upvotes: 2

Related Questions