1

I am trying to do something similar to the codes below, adding a list with an index as the key in to a dictionary.

import random

rand_list = []
rand_dict = {}

for i in range(1, 10):
    for j in range(1, 3):
        rand_list.append(random.randint(1, 10))

    rand_dict.update({i: rand_list})
    rand_list.clear()

print(rand_dict)

the output i get

{1: [], 2: [], 3: [], 4: [], 5: [], 6: [], 7: [], 8: [], 9: []}

As I don't want the rand_list contain any existing generated numbers, I've cleared the content in rand_list after added into rand_dict. But surprisingly, rand_dict values get deleted as well, am I doing something wrong here?

ReverseEngineer
  • 529
  • 1
  • 5
  • 18

1 Answers1

2
import random

rand_list = []
rand_dict = {}

for i in range(1, 10):
    for j in range(1, 3):
        rand_list.append(random.randint(1, 10))

    rand_dict.update({i: rand_list.copy()})
    rand_list.clear()

print(rand_dict)

Dictionaries store references to some variables rather than the actual value, there for a clear() would affect the dictionary as well. (If I would try to go into the world of theory, this is what you'd call mutable variables. Lists being one of those. While a variable with a integer would be copied rather than references)

Instead, make a copy of it before you wipe it. That way any modifications to the original value won't affect the dict. Or rethink your approach.

One other approach that @deceze points out, which is a more traditional way of solving this is putting the list creation in the loop.

import random

rand_dict = {}

for i in range(1, 10):
    rand_list = []
    for j in range(1, 3):
        rand_list.append(random.randint(1, 10))

    rand_dict.update({i: rand_list.copy()})

print(rand_dict)

That way, each iteration is a new instance of a list. Essentially doing the same thing as clearing it. My terminology might be off here tho, I'm more of a practitioner/dabbler than a theoretician.

One useful tool to see why this happens, and why the last approach works, is by doing:

for i in range(1, 10):
    rand_list = []
    print(hex(id(rand_list))) # <--

This prints the memory address of the variable. If it stays the same after each clear() or value in the dict, you know it's a referenced value.

Torxed
  • 22,866
  • 14
  • 82
  • 131
  • 2
    It would make much more sense to simply move `rand_list = []` into the loop. – deceze Oct 21 '18 at 08:11
  • @deceze I was thinking the same thing. But saw this as a opportunity to "teach" how the dicts behave. – Torxed Oct 21 '18 at 08:12
  • @deceze, I understand that. I just want to point out my question on how the dict works. Anyway, thank you – ReverseEngineer Oct 21 '18 at 08:15
  • @ReverseEngineer You can do pretty neat things with dictionaries once you figure out how they work. Personally, I like to think of them as a pointer class. Anyway, if you find the answer helpful I'd appreciate if you mark mine or any one elses answers as the solution. Best of luck! – Torxed Oct 21 '18 at 08:16
  • Why not create a new list directly in the dictionary, rather than copy an existing list into the dictionary, like so? for i in range(10): rand_dict[i] = [random.randint(1,10) for _ in range(3)] – Mario Camilleri Oct 21 '18 at 08:18
  • @mkam Why not just `rand_dict = dict(enumerate(range(3)))` :) There's a million takes on how this could be done. Question was regarding how the dicts work I think. – Torxed Oct 21 '18 at 08:24
  • 1
    @mkam, it just to illustrating my question on how dict works. It's not a actual codes I am currently working on. – ReverseEngineer Oct 21 '18 at 08:24
  • @ReverseEngineer - my point was that the problem arose because you were trying to copy the list into the dictionary. Creating the list directly inside the dictionary avoids the problem. – Mario Camilleri Oct 21 '18 at 08:28
  • @Torxed - I don't think rand_dict = dict(enumerate(range(3))) will score highly in the randomness stakes ;-) It only produces {0: 0, 1: 1, 2: 2} – Mario Camilleri Oct 21 '18 at 08:31
  • 1
    @mkam, got your point, will consider that approach, thanks! – ReverseEngineer Oct 21 '18 at 09:00