Python Forum

Full Version: assign a value to a dict change all the values
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2

i am really getting mad with these few lines of code

from random import randint

header = ["test", "1", "2", "12", "GG", "NG"]
lis = ["alpha", "beta", "gamma"]

list_p = list()
dict_p = dict.fromkeys(header)

def random():

    for item in lis:
        dict_p["test"] = item
        for key in list(dict_p.keys())[1:]:
            dict_p[key] = randint(1,600)/100.0

    return list_p

i know from here that Changing One dict value changes all values in a list and even if i feel completely dumb i am not able to apply these answers to my case

could you explain what i am doing wrong? Wall
could you explain what you think is wrong, what to expect the results should be, any error messages, etc,
In other words something to go on.
List are reference variables. They are always pass as reference.
When you assign one list to all variables.
It all point to the same list.

import numpy as np
td =[np.Inf, 2, 3]
a = {}

for k in range(10):
    a[k] = td # point to one list

a[0][0] = 1
td[1] = 10
for i in a.items():

b = {}
for k in range(10):
    b[k] = td[:] # shallow copy

b[0][0] = 2
td[1] = 0
for i in b.items():
a = [1, 2, 3]
b = a
c = a[:] # shallow copy


a[1] = 6
b[0] = 5
c[2] = 7

Windspar thank you for your second example i didn t know about shallow copy

Anyway i think that my problem isn t caused by the absence of a shallow copy

Posting that stackexchange i brought you outside the road sorry
As Larz60+ suggested this is my aim:
In my code i am creating a dict with random numbers (dict_p) then i would like to add (append) this dict to a list (list_p)
This is my output
[{'test': 'gamma', '12': 3.89, 'NG': 0.06, '1': 2.82, '2': 4.31, 'GG': 0.95}, {'test': 'gamma', '12': 3.89, 'NG': 0.06, '1': 2.82, '2': 4.31, 'GG': 0.95}, {'test': 'gamma', '12': 3.89, 'NG': 0.06, '1': 2.82, '2': 4.31, 'GG': 0.95}]
It shouldn t be all the same. For some reason that i don t understand the list is filled always with the last appended dict
I would like that is was filled with different random generated dict
Appending the variable for the dict just appends a pointer to where the dict is stored (the reference Windspar is talking about). The list items are all pointing to the same place, where the current value of the dict is stored. That's why you are seeing the last version of the dict repeated, because that is what is stored when you display it.

If you want to save the current state to the list, change the append to list_p.append(dict_p.copy()). That will create the shallow copy. Note that this won't work in all cases. Sometimes you need a deep copy.
thanks ichabod801 now almost everything is perfectly clear :) stupidly i thought that the reference you were talking about was referred to the list and not to the dict, now i understand it was a general explanation about how python works
i re adapted the example of @Windspar to my case

a = {'a':1,'b':2,'c':3}
b = a
c = a.copy() # shallow copy
a['a'] = 6
b['b'] = 5
c['c'] = 7
now i am only confused by all these term that for me are completely news: copy, shallow copy and deep copy

i guess that the pro of the shallow copy is that the code is faster and one cons could be that it bring newby like me to this error :P
i have a doubt, from wikipedia says under the voice shallow copy: The referenced objects are thus shared, so if one of these objects is modified (from A or B), the change is visible in the other. Why in my case i didn't need a deep copy? and how it is possible that a shallow copy worked? is there any difference between a shallow copy and a "reference-copy"?
The list is a reference too, just like the dictionary. A shallow copy of the list gives you all the items in the list. But some of those items can be references too. A shallow copy will just give you those references.

>>> x = [1, 2, 3]
>>> y = [x, 4, 5]
>>> y
[[1, 2, 3], 4, 5]
>>> z = y[:]  # shallow copy
>>> y[1] = 6
>>> y
[[1, 2, 3], 6, 5]
>>> z
[[1, 2, 3], 4, 5] # integers that are values don't have changes affect the shallow copy
>>> x[1] = 7
>>> z
[[1, 7, 3], 4, 5] # lists that are references do have changes affect the shallow copy
A deep copy would make an independent copy of everything in the list.
Wowwwwww before i wouldn t never thought that it had such this behaviour! Now it is more clear, i also feel a "fear" (for unexpected behaviour) to use everything which isn t a deep copy ?
Edit: Tomorrow i will try your example with tuples, i am really curios about it
You can't assign to a tuple index, so it won't work. This is an important point in Python. Mutables, like lists, dictionaries, and sets, display the behavior you see above. Immutables, like numbers, strings, and tuples, do not.
(Sep-21-2018, 02:43 AM)ichabod801 Wrote: [ -> ]You can't assign to a tuple index, so it won't work. This is an important point in Python. Mutables, like lists, dictionaries, and sets, display the behavior you see above. Immutables, like numbers, strings, and tuples, do not.

yes i know, what i wanted to check is if i can change the item pointed by a reference

from copy import deepcopy

x = [1, 2, 3]
y = (x, 4, 5)

z = deepcopy(y)
x[1] = 7
and i can, please tell me if i am wrong: i can change it because the reference of 'x' inside y is always the same Dance
but so which is the difference between a normal copy and a shallow copy?
i am almost sure that i understood correctly the difference between a copy and a deep copy, the last one is completely a new object while the first is a reference to the original object
Pages: 1 2