Bijoy
Bijoy

Reputation: 1131

Multidimension array created, but output not as Expected

I have a doubt when i create a multidimentional array with None element, i.e. all elements are having same id but only elements of a single row are changed.

def array(a, b):
    none = [None for _ in range(b)]
    return [none for _ in range (a)]

So now arr = array(4, 5) gives

[[None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None]]

Now when I do arr[0][4] = 45 It gives

[[None, None, None, None, 45],
[None, None, None, None, 45],
[None,None, None, None, 45], [None, None, None, None, 45]]

Every 4th index value is changed to 45 So I tried

def id_array(a, b):
    none = [id(None) for _ in range(b)]
    return [none for _ in range (a)]

Now id_arr = id_array(4, 5)

[[138022184, 138022184, 138022184, 138022184, 138022184], [138022184, 138022184, 138022184, 138022184, 138022184], [138022184, 138022184, 138022184, 138022184, 138022184], [138022184, 138022184, 138022184, 138022184, 138022184]]

i.e. every value has same id so while doing arr[0][4] = 45 shouldn't every value of arr change to 45 because everyone has same id and why only 4th index of every row being changed.

Upvotes: 1

Views: 60

Answers (2)

greole
greole

Reputation: 4771

In your example you are creating a list of identical lists, i.e references to exact same list. If you check the Ids

>>> def array(a, b):
       none = [None for _ in range(b)]
       return [none for _ in range (a)]

>>> bs = array(4,5)
>>> [id(b) for b in bs]
[139931681000480, 139931681000480, 139931681000480, 139931681000480]

If you arr[0][4] = 45 you simply changing what the fourth list element points to and not the None element self. It becomes more clear if you add a list with distinct id

>>> bs.append([1,2,3,4])
>>> bs[0][1] = 1
>>> bs
[[None, 1, None, None, None],
 [None, 1, None, None, None],
 [None, 1, None, None, None],
 [None, 1, None, None, None],
 [1, 2, 3, 4]]

Upvotes: 0

gyre
gyre

Reputation: 16779

You're reusing the same none list for every element you append to your return value, when you want each one to be distinct. That's why updates to none via one index are reflected across all others — because you are editing only a single list, even though you may have multiple references to it.

The way to remedy this behavior is to simply place the first comprehension inside the second:

def array(a, b):
    return [[None for _ in range(b)] for _ in range (a)]

Upvotes: 3

Related Questions