Reputation: 117
The code is passed an array. My understanding is this passing is done by reference. I want the function to recursively divide the last remaining half of the list in two and set each value that it was split at to zero. The change to zero is happens in the array but when I call print a at the end I get the original array.
What am i doing wrong?
a = range(10)
def listreduction(array):
if len(array) == 1:
array[0] = 0
return
split = len(array)/2
array[split] = 0
return listreduction(array[split:])
listreduction(a)
print a
The current output is
[0, 1, 2, 3, 4, 0, 6, 7, 8, 9]
The should be more zeros to the right of the second one
Upvotes: 0
Views: 72
Reputation: 1877
In Python argumnet passing is different from other conventional programming language. arguments are passed by object reference. And the whether the referred object will be modifed or not it depends on two things
range
will create a list so its a mutable object. That implies that if you update array
it should also update a
. =
operation will always create new object reference. So even in your case array
is mutable but since you are doing assignment operation It will create a new object reference. Following example should clear up the things for you.
Example 1
>>> a = [1,2]
def fun1(array):
array= array + [3]
print "var array = %s" %array
fun1(a)
print "var a = %s" %a
Output
var array = [1, 2, 3]
var a = [1, 2]
Example 2
a = [1,2]
def fun1(array):
array.append(3)
print "var array = %s" %array
fun1(a)
print "var a = %s" %a
Output
var array = [1, 2, 3]
var a = [1, 2,3]
Upvotes: 1
Reputation: 2771
Since you use recursion, the slice operation in the argument will create new list instance which is different than you instance. That's the reason.
You can change your code as following:
a = range(10)
def list_reduction(array, position=0):
if len(array) -1 <= position:
return
split = position + (len(array) - position) / 2
array[split] = 0
return list_reduction(array, split)
list_reduction(a)
print a
The output is:
[0, 1, 2, 3, 4, 0, 6, 0, 0, 0]
Upvotes: 1
Reputation: 757
This is probably what you want.
a = range(1, 10)
def list_reduction(l, prev_split_pos=None):
split_pos = (len(l) + prev_split_pos) / 2 if prev_split_pos else len(l) / 2
if split_pos == prev_split_pos:
return
l[split_pos] = 0
return list_reduction(l, split_pos)
list_reduction(a)
print a
So, to your code. Everytime you do a list slice, you actually generate a new list, which is not at all connected to the old one. This is why you don't see any mutations to it except the first one.
Upvotes: 1
Reputation: 41898
A slice creates a new list. If you want to do this recursively, you'll have to pass the index where the function is supposed to work on the list, not the actual slice.
Upvotes: 2