user3079275 -4 years ago 74
Python Question

# List pass by reference confusion in Python

I have this snippet of code that just sorts a list of numbers that are guaranteed to be between 0 and R-1 (inclusive). The following code does the sort correctly but I don't understand why the input passed in remains unmodified.

def bucket(arr, R):
assert type(arr) is list
for i in arr:
assert i >=0 and i < R
b = [0] * R
for i in arr:
b[i]+=1
arr = []
for ind, v in enumerate(b):
arr = arr + [ind] * v
print(arr)

Why is
inp
in this example unchanged after the function has been called:

>>> inp
[3, 1, 4, 5, 4, 5, 5, 5, 1, 5]
>>> bucket(inp, 8)
[1, 1, 3, 4, 4, 5, 5, 5, 5, 5]
>>> inp # unchanged, why?
[3, 1, 4, 5, 4, 5, 5, 5, 1, 5]

Because you create a new variable called arr in the line arr = [] and from this point on you operate on a new list. Similarly you always create new lists inside the following for-loop with the arr = arr + [ind] * v operations.

You could simply change it to:

def bucket(arr, R):
assert type(arr) is list
for i in arr:
assert i >= 0 and i < R
b = [0] * R
for i in arr:
b[i] += 1
arr[:] = []  # remove all items from the list (in-place)
for ind, v in enumerate(b):
arr.extend([ind] * v)  # extend the list in-place, you could also use "arr += [ind] * v"
print(arr)

Example:

>>> inp = [3, 1, 4, 5, 4, 5, 5, 5, 1, 5]
>>> bucket(inp, 8)
[1, 1, 3, 4, 4, 5, 5, 5, 5, 5]
>>> inp
[1, 1, 3, 4, 4, 5, 5, 5, 5, 5]
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download