Lists within lists: even slicing, there is connection between lists

4

I am studying lists and behavior occurs that I do not understand.

I know that when I link one list to another, a connection between them is created. And that when I use slicing a list, I create a copy of the list (no connection between them, that is, when it changes into mute, it does not change in another). However, when there are lists within lists, even with slicing, connection is made between lists.

For example:

>>> a = [[2, 3, 5], [1, 3, 5]]
>>> b = a[:]
>>> print(b)
[[2, 3, 5], [1, 3, 5]]
>>> b[0][1] = 100
>>> print(a[0][1])
100
>>> print(b)
[[2, 100, 5], [1, 3, 5]]
>>> print(a)
[[2, 100, 5], [1, 3, 5]]

That is, changed in the b list, also changed in the a list. Why did this happen?

    
asked by anonymous 04.11.2018 / 23:19

3 answers

2

A more detailed explanation.

Each list is a separate object. there is no "list a" or "list b". In python, unlike many other languages, variables are just names that refer to objects .

Let's look at the code line by line:

a = [[2, 3, 5], [1, 3, 5]]

This line is creating 3 lists. One of the lists has references to the other two lists within it. the name a is pointing to one of the 3 created lists, the one containing the other two lists. To say that this is "list a" is a simpler way of saying, but in fact that is not the a list. a is only a "name" that "references" the list.

b = a[:]

This line does two things: When you use [:] with a list, a new list is created, where all the references that were in the original list are copied. A b name is then created to refer to this copy.

At this point, you have 4 lists: These are the ones in the order they were created:

PRIMEIRA LISTA:  [2, 3, 5]
SEGUNDA LISTA: [1, 3, 5]
TERCEIRA LISTA: [(PRIMEIRA LISTA), (SEGUNDA LISTA)]
QUARTA LISTA: [(PRIMEIRA LISTA), (SEGUNDA LISTA)]

See that the contents of the third list are the same as those of the fourth list, that is, references have been copied that point to the first two lists ... that is what the [:] makes , copy references .

So, it does not matter if you use a or b to refer to the third or fourth list, because at the end of the processing, when you tinker with internal lists, you're moving on the same list! >     

05.11.2018 / 00:20
3

You are using slice which is nothing more than a reference to the concrete list, just like any list, so if changing something by reference will be changing in the original list, it is the same internally. The variables are different, but the object they refer to is the same.

If you do not want this you need to make a deep copy where each element is actually copied to a new, isolated, concrete list. So:

import copy

a = [[2, 3, 5], [1, 3, 5]]
b = copy.deepcopy(a)
b[0][1] = 100
print(a)

See running on ideone . And no Coding Ground . Also I put GitHub for future reference .

You have other ways to get the same, but what you need to understand is the concept of reference and actual copying. Of course the reference is super fast and has constant time complexity (O (1)) and the actual copy is much slower and has linear complexity (O (N)).

An important detail based on other points on this page: Python is no different than other languages, all work the same. There are authors on Python who sell this idea that it is different, but it is not. In general, those who learn only from these sources believe in this. There are differences from Python to other languages, but these concepts are universal. In all languages everything that is state is object, has response here on the site about it , and variables are always names for memory addresses where you have the objects . You may also be interested in: Is everything object in Python? .

    
04.11.2018 / 23:39
0
  

changed in list b, also changed in list a

You did not changed the b list. What you have changed is a list that is within of b . This inner list is shared between a and b , because the slice (slicing) operation does a shallow copy .

See:

a = [[1, 2, 3], [4, 5, 6]]
b = a[:]

a[0] = [7, 8, 9]

print(a)
print(b)

Note that even though% as% has changed, a has remained the same. However, if you do this here:

a[1][0] = 0

print(a)
print(b)

The change will be seen in both% and% with%, because in this second case the change occurred in the internal list , and this internal list is the same in b and a .

If you want to copy the internal lists too, use b as indicated in this other response .

    
06.11.2018 / 17:57