1

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.

gyre
  • 16,369
  • 3
  • 37
  • 47
Bijoy
  • 1,131
  • 1
  • 12
  • 23
  • Possible duplicate of [Python list problem](http://stackoverflow.com/questions/1959744/python-list-problem) – xrisk Apr 08 '17 at 07:47
  • I know it create duplicate of same list, I was confused about same `id`, and above question doesnt clearify that . – Bijoy Apr 08 '17 at 08:05

2 Answers2

3

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)]
gyre
  • 16,369
  • 3
  • 37
  • 47
  • Yes but every element is having same id, why is only the given index value being changed of every row – Bijoy Apr 08 '17 at 07:47
  • Each integer `id` is at a distinct position in the list, and since such primitive numeric types are passed by value, changing the value at one index does not trigger any changes in other places. Only the `none` list reference is reused — each `id` is an int with its own place in memory. – gyre Apr 08 '17 at 07:49
  • @Bijoy yes but more importantly the list ids are the same in your example. So when you edit the list arr[0] you edit all lists, since they are the same. – greole Apr 08 '17 at 07:49
  • ohh so while changing both `id` and the position of the `element` in the list is checked, am i right – Bijoy Apr 08 '17 at 07:52
  • @greole Exactly. This is where reusing references becomes problematic, because for the vast majority of cases this behavior is undesirable. – gyre Apr 08 '17 at 07:52
0

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]]
greole
  • 4,523
  • 5
  • 29
  • 49