0

I have a 5x2 dimensional array which I want to assign specific values to, but I'm having trouble doing so even looking at multiple explanations of Python passing by value rather than reference. The relevant code is as follows:

def do_something(x, y):
    x = 0
    y = 0
    return_value = -1 #error may occur in this code
    #some complex operation is performed that manipulates x and y
    return_value = 0
    return return_value

def main():
    result = [[0]*5]*2
    for i in range(5):
         do_something(result[i][0], result[i][1])

I clearly can't say result = do_something(...) because I still want to know what do_something returned to see if the complex operation is done right. Append doesn't exactly solve my problem, because x and y are manipulated inside the code. Result[i].append(...) would work if I knew what I wanted to append. But even when the complex operation goes right, the array doesn't change. (I have tried passing result, then r.append(...) but that doesn't work either) Any help?

VietHTran
  • 2,233
  • 2
  • 9
  • 16
Goodwin Lu
  • 45
  • 1
  • 12
  • Does the function arguments have to be `x, y` or it can include other arguments? – VietHTran Apr 20 '19 at 01:31
  • You almost certainly want `[[0]*5 for _ in range(2)]` so that the two rows are independent. Your current code is a list of two references to the *same* row of 5 0s. – chepner Apr 20 '19 at 02:43
  • Related: https://stackoverflow.com/questions/240178/list-of-lists-changes-reflected-across-sublists-unexpectedly – Blckknght Apr 20 '19 at 02:55

3 Answers3

0

There is no problem in do_something function.

At main function,

result = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]

So, please change as below code.
do_something(result[0][i], result[0][i])

Wang Liang
  • 4,244
  • 6
  • 22
  • 45
0

Python does pass parameters by reference. However, there are two points to consider:

First, when passing immutable types like integers, floats, strings etc. they will not be effected by the code running in the function.

x = 1.0
def int_do_somthing(x):
    x += 1
int_do_somthing(x)
print(x) # 1.0

Second, when you reassign the value of a variable to a new variable within the function scope, the original one is not effected.

l = [1,1,1]

def do_nothing(l):
    l = l + [2] # defines a new l that only exist in the function scope

do_nothing(l)
print(l) # [1,1,1]

def do_somthing(l):
    l += [2] # modify existing l

do_somthing(l)
print(l) # [1,1,1,2]

So in your case, pass array slices, not individual values to the function, and dont reassign the entire slice but rather edit the values they contain (access with [] operator).

Yosi Hammer
  • 588
  • 2
  • 8
0

result[i][0] and result[i][1] are integer type values. Since integer is primitive type, changing their values inside the function won't affect the actual values outside the list. You should pass in the list instead since it is not a primitive type and thus any changes you made inside the function will also affect the list outside the function. Also, you probably don't want to use result = [[0]*5]*2 to initialize your array. One reason is that it will initialize a 2x5 array instead of 5x2. The other more important reason is that it will only duplicate the reference to the list [0, 0, 0, 0, 0] twice. Therefore, if you change only 1 value inside a row, the other row will also have that value. For example:

result = [[0] * 5] * 2
print(result) # This will print out [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
result[0][1] = 1
print(result) # This will print out [[0, 1, 0, 0, 0], [0, 1, 0, 0, 0]]

The alternative way you can do is to use result = [[0 for x in range(5)] for y in range(2)] which will give array with desired values but they are not duplicated reference like the above.

result = [[0 for x in range(5)] for y in range(2)]
print(result) # This will print out [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
result[0][1] = 1
print(result) # This will print out [[0, 1, 0, 0, 0], [0, 0, 0, 0, 0]]

I've modified your code according to my suggestion and it seems to work well:

def do_something(arr):
    # Assign value below
    arr[0] = 1
    arr[1] = 2

def main():
    result = [[0 for x in range(2)] for y in range(5)]
    for i in range(5):
         do_something(result[i])
    print result

main()
VietHTran
  • 2,233
  • 2
  • 9
  • 16