Asigning new random list to nested dictionary assigns last seen list to all

Viewed 40

As described in the title I'm trying to assign a dictionary with lists as values that are random to parent dictionary. An unexpected thing is that when I want to assign it to parent dictionary then I only get the latest dictionary assigned. Please see code example:

temp = {}
d = {}
for x in range(3):
    for i in range(3):
        temp[i] = list(np.random.randint(10, size=10))
    print(x)
    print(temp)
    d[x] = temp
    print(d[x])
print("--------------------------")
print("The final dictionary: ", d)


0
{0: [1, 4, 1, 7, 3, 9, 3, 8, 1, 5], 1: [6, 5, 2, 0, 5, 0, 5, 9, 7, 1], 2: [7, 9, 3, 3, 5, 8, 6, 0, 6, 0]}
{0: [1, 4, 1, 7, 3, 9, 3, 8, 1, 5], 1: [6, 5, 2, 0, 5, 0, 5, 9, 7, 1], 2: [7, 9, 3, 3, 5, 8, 6, 0, 6, 0]}
1
{0: [0, 0, 7, 0, 0, 1, 9, 9, 2, 0], 1: [1, 5, 8, 7, 2, 9, 0, 8, 7, 9], 2: [8, 8, 4, 8, 1, 1, 1, 2, 4, 4]}
{0: [0, 0, 7, 0, 0, 1, 9, 9, 2, 0], 1: [1, 5, 8, 7, 2, 9, 0, 8, 7, 9], 2: [8, 8, 4, 8, 1, 1, 1, 2, 4, 4]}
2
{0: [5, 4, 7, 1, 1, 3, 0, 3, 6, 9], 1: [5, 9, 7, 8, 0, 7, 1, 7, 6, 9], 2: [4, 2, 6, 1, 3, 7, 2, 6, 4, 8]}
{0: [5, 4, 7, 1, 1, 3, 0, 3, 6, 9], 1: [5, 9, 7, 8, 0, 7, 1, 7, 6, 9], 2: [4, 2, 6, 1, 3, 7, 2, 6, 4, 8]}
--------------------------
The final dictionary:  {0: {0: [5, 4, 7, 1, 1, 3, 0, 3, 6, 9], 1: [5, 9, 7, 8, 0, 7, 1, 7, 6, 9], 2: [4, 2, 6, 1, 3, 7, 2, 6, 4, 8]}, 1: {0: [5, 4, 7, 1, 1, 3, 0, 3, 6, 9], 1: [5, 9, 7, 8, 0, 7, 1, 7, 6, 9], 2: [4, 2, 6, 1, 3, 7, 2, 6, 4, 8]}, 2: {0: [5, 4, 7, 1, 1, 3, 0, 3, 6, 9], 1: [5, 9, 7, 8, 0, 7, 1, 7, 6, 9], 2: [4, 2, 6, 1, 3, 7, 2, 6, 4, 8]}}
2 Answers

Your problem is, that in the line d[x] = temp you are just referencing on the same object and when you overwrite temp, you also overwrite all existing links to it. The problem is called shallow vs deep copy. There are multiple ways, to create a 'real' copy, but the copy library offers two functions copy, deepcopy that do just that. Notice, for nested objects, you need the deepcopy function

from copy import copy


temp = {}
d = {}
for x in range(3):
    for i in range(3):
        temp[i] = list(np.random.randint(10, size=10))
    print(x)
    print(temp)
    d[x] = copy(temp)

    print(d[x])
print("--------------------------")
print("The final dictionary: ", d)

{0: [2, 7, 9, 5, 2, 6, 1, 9, 9, 4], 1: [1, 0, 1, 9, 6, 1, 6, 4, 2, 3], 2: [9, 1, 1, 2, 1, 3, 5, 5, 5, 2]}
{0: [2, 7, 9, 5, 2, 6, 1, 9, 9, 4], 1: [1, 0, 1, 9, 6, 1, 6, 4, 2, 3], 2: [9, 1, 1, 2, 1, 3, 5, 5, 5, 2]}
1
{0: [3, 0, 8, 0, 7, 1, 9, 9, 0, 6], 1: [4, 1, 5, 0, 7, 5, 8, 9, 8, 3], 2: [7, 2, 7, 5, 8, 5, 5, 4, 6, 0]}
{0: [3, 0, 8, 0, 7, 1, 9, 9, 0, 6], 1: [4, 1, 5, 0, 7, 5, 8, 9, 8, 3], 2: [7, 2, 7, 5, 8, 5, 5, 4, 6, 0]}
2
{0: [0, 2, 3, 3, 5, 6, 8, 9, 0, 9], 1: [5, 2, 2, 4, 6, 5, 3, 8, 7, 3], 2: [1, 6, 5, 3, 7, 1, 3, 3, 4, 4]}
{0: [0, 2, 3, 3, 5, 6, 8, 9, 0, 9], 1: [5, 2, 2, 4, 6, 5, 3, 8, 7, 3], 2: [1, 6, 5, 3, 7, 1, 3, 3, 4, 4]}
--------------------------
The final dictionary:  {0: {0: [2, 7, 9, 5, 2, 6, 1, 9, 9, 4], 1: [1, 0, 1, 9, 6, 1, 6, 4, 2, 3], 2: [9, 1, 1, 2, 1, 3, 5, 5, 5, 2]}, 1: {0: [3, 0, 8, 0, 7, 1, 9, 9, 0, 6], 1: [4, 1, 5, 0, 7, 5, 8, 9, 8, 3], 2: [7, 2, 7, 5, 8, 5, 5, 4, 6, 0]}, 2: {0: [0, 2, 3, 3, 5, 6, 8, 9, 0, 9], 1: [5, 2, 2, 4, 6, 5, 3, 8, 7, 3], 2: [1, 6, 5, 3, 7, 1, 3, 3, 4, 4]}}

In my point of view, the problem is you use same temp for all.

So just move statement temp = {} after for x in range(3):

import numpy as np

d = {}
for x in range(3):
    temp = {}
    for i in range(3):
        temp[i] = list(np.random.randint(10, size=10))
    print(x)
    print(temp)
    d[x] = temp
    print(d[x])
print("--------------------------")
print("The final dictionary: ", d)
Related