Q:

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]

A:

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]

