11

First of all, sorry if this questions is extremely basic, I'm just starting with Python.

I'm having problems understanding how Python 3.6 creates and appends objects to lists. See the following code:

a_dict=dict()
a_list=list()

for i in range(100):
  a_dict['original'] = i
  a_dict['multi'] = i*2
  a_list.append(a_dict)

The print of the list goes like

print(a_list)
>>[{'original': 99, 'multi': 198}{'original': 99, 'multi': 198}...{'original': 99, 'multi': 198}]

According to my original thoughts, i=0 -> original=0, multi=0; i=1 -> original=1, multi=2; etc...

But, according to this question here, Python's append() appends a pointer to the object not the actual value. So I change the append(original) on my original code to append(copy):

a_dict=dict()
a_list=list()

for i in range(100):
  a_dict['original'] = i
  a_dict['multi'] = i*2
  a_list.append(a_dict.copy()) ##change here

Now, I get the desired result:

print(a_list)
[{'original': 0, 'multi': 0}, {'original': 1, 'multi': 2}, {'original': 2, 'multi': 4},...]    

Now, here is my question:

How append() really works? Do always lists contain pointers-like objects to their originals? How about other types? Should I always use copy() if my intentions are not to directly mess with the original values or the list/container I'm using?

Hope I'm explaining myself good enough. And again sorry if it's a basic question. Thanks.

Community
  • 1
  • 1
alezvic
  • 344
  • 1
  • 4
  • 20
  • 3
    Your code would be simpler if you just created a new blank dictionary at the start of each iteration of the for loop. But it's not clear what your question is, apart from what is already covered in the linked question. – Daniel Roseman May 10 '17 at 14:32
  • @DanielRoseman, yes, I know it's a confusing question. Anyway, you're right about the new dictionary at the beginning of each loop. – alezvic May 10 '17 at 22:03

1 Answers1

5

This has to do with mutability of the objects you append. If the objects are mutable, they can be updated, and you essentially add a reference to your list with the .append() function. Thus in these situations you need a copy.

A pretty good list of which types are mutable and not is found on this site. However, generally, container types tend to be mutable whereas simple values typically are immutable.

JohanL
  • 6,671
  • 1
  • 12
  • 26
  • "simple values typically are immutable" - so an int is immutable? – Kami Kaze Jan 13 '20 at 08:44
  • 2
    That is correct. The `int` itself is immutable. However, a variable pointing to an `int` can be updated to point to antoher (immutable) `int`. So, the variable can change value, even though the `int` object itself is immutable. – JohanL Jan 13 '20 at 11:52