0

Why is this list r getting altered even if I am only trying to make changes in list v? Even though they do not point to same memory location.

r = v = list()
r = [[2,2,1],[2,8,3],[10,2,1],[8,4,2],[4,6,4]]
for c, a in enumerate(r):
    if len(v) > 0:
        v[0][0]=c
        v[0][1]=c
    v.append(a)
print('r',r)
print('v',v)
print(hex(id(r)))
print(hex(id(v)))
blhsing
  • 91,368
  • 6
  • 71
  • 106
Utkarsh
  • 137
  • 9
  • can you properly format this? – marcos Feb 20 '20 at 18:45
  • 2
    You put references to `r`'s sublists into `v` and then change them. Since r and v share the same sublists, changing one changes the other. If you don't want that, try `v.append(a[:])` to make a copy of the sublist. – tdelaney Feb 20 '20 at 18:49
  • Tons of similar questions like yours, such ad [python list.pop() modifies original list (not just copy)](https://stackoverflow.com/questions/35120380/python-list-pop-modifies-original-list-not-just-copy). – Jongware Feb 20 '20 at 19:25
  • Does this answer your question? [Why does foo.append(bar) affect all elements in a list of lists?](https://stackoverflow.com/questions/6360286/why-does-foo-appendbar-affect-all-elements-in-a-list-of-lists) – AMC Feb 20 '20 at 19:28

3 Answers3

0

Add the following 2 lines to your code and see the output.

print(hex(id(r[0])))
print(hex(id(v[0])))

The output I got is -

('r', [[4, 4, 1], [2, 8, 3], [10, 2, 1], [8, 4, 2], [4, 6, 4]])
('v', [[4, 4, 1], [2, 8, 3], [10, 2, 1], [8, 4, 2], [4, 6, 4]])
id(r) 0x39ccb48L
id(v) 0x17626c8L
id(r[0]) 0x39cc7c8L
id(r[0]) 0x39cc7c8L

Although 'r' and 'v' are different, r[0] and v[0] point to the same object. Hence, modifying v[0] also modifies r[0].

sri
  • 359
  • 2
  • 5
0

Your code

>>> id(r) == id(v)
True

Substitute r,v=[],[]

>>> id(r) == id(v)
False

It is better to place the condition code after the variable is defined (Add to line 2)

Nima
  • 323
  • 4
  • 13
0

v.append(a) adds a reference to r's sublists to v. r and v are different, but their contained items are the same. Expand your prints to include the sublists and you'll see

r = v = list()
r = [[2,2,1],[2,8,3],[10,2,1],[8,4,2],[4,6,4]]
for c, a in enumerate(r):
    if len(v) > 0:
        v[0][0]=c
        v[0][1]=c
    v.append(a)
print('r',r)
print('v',v)
print(hex(id(r)),[hex(id(i)) for i in r])
print(hex(id(v)),[hex(id(i)) for i in v])

I get

r [[4, 4, 1], [2, 8, 3], [10, 2, 1], [8, 4, 2], [4, 6, 4]]
v [[4, 4, 1], [2, 8, 3], [10, 2, 1], [8, 4, 2], [4, 6, 4]]
0x7f7f0d4e8848 ['0x7f7f0d55ff88', '0x7f7f0d55ffc8', '0x7f7f0d38c708', '0x7f7f0d38c648', '0x7f7f0d3a0ac8']
0x7f7f0d3a0c48 ['0x7f7f0d55ff88', '0x7f7f0d55ffc8', '0x7f7f0d38c708', '0x7f7f0d38c648', '0x7f7f0d3a0ac8']

If you want the lists to be independent, copy the sublists. All I did was change v.append(...) (and removed the initial assignment to r which was unneeded)

v = list()
r = [[2,2,1],[2,8,3],[10,2,1],[8,4,2],[4,6,4]]
for c, a in enumerate(r):
    if len(v) > 0:
        v[0][0]=c
        v[0][1]=c
    v.append(a[:])
print('r',r)
print('v',v)
print(hex(id(r)),[hex(id(i)) for i in r])
print(hex(id(v)),[hex(id(i)) for i in v])

Which gives

r [[2, 2, 1], [2, 8, 3], [10, 2, 1], [8, 4, 2], [4, 6, 4]]
v [[4, 4, 1], [2, 8, 3], [10, 2, 1], [8, 4, 2], [4, 6, 4]]
0x7fa258a91848 ['0x7fa258b08f88', '0x7fa258b08fc8', '0x7fa258935748', '0x7fa258935688', '0x7fa258949b08']
0x7fa258949c88 ['0x7fa2589357c8', '0x7fa258a915c8', '0x7fa258949d08', '0x7fa258949d88', '0x7fa258949dc8']
tdelaney
  • 73,364
  • 6
  • 83
  • 116