0

Can anyone explain this? Why are all elements of yeartonametolist affected when I just change one?

yeartonametolist = dict.fromkeys(range(2007,2017),{})
yeartonametolist[2007]["a"] = 1
yeartonametolist[2008]["b"] = 2
print yeartonametolist

Output:

{ 
  2016: {'a': 1, 'b': 2}, 
  2007: {'a': 1, 'b': 2}, 
  2008: {'a': 1, 'b': 2}, 
  2009: {'a': 1, 'b': 2}, 
  2010: {'a': 1, 'b': 2},
  2011: {'a': 1, 'b': 2}, 
  2012: {'a': 1, 'b': 2}, 
  2013: {'a': 1, 'b': 2}, 
  2014: {'a': 1, 'b': 2}, 
  2015: {'a': 1, 'b': 2}
}
mugabits
  • 1,015
  • 1
  • 12
  • 22
  • First observation, you are using a dictionary. Not a list. – mugabits Jul 06 '17 at 14:25
  • @jmugz3 May you explain please? I said it's a dictionary. Are the components of a dictionary not called elements? Thank you. – user1920468 Jul 06 '17 at 14:27
  • would it be surprising enough if i said that when you create you dict as follow `yeartonametolist = {a:{} for a in range(2007,2017)}` the problem disappears ? I think it's something related to `dict.fromkeys` but I didn't find anything about that.. @user1920468 – Rayhane Mama Jul 06 '17 at 14:31
  • @RayhaneMama Thank you. That seems to fix it. – user1920468 Jul 06 '17 at 14:46
  • oh you just wanted a fix ? not to understand why ? happy could help then :p i'll just post it as answer cuz.. well that's the policy xD and for future users as well ;) @user1920468 – Rayhane Mama Jul 06 '17 at 14:49
  • @RayhaneMama Don't post a half answer for the sake of rep... try to understand what the issue is yourself and then add that to your answer. – cs95 Jul 06 '17 at 14:50
  • By the way the reason is that all the `{}` in `yeartonamelist` belong to the same object. – cs95 Jul 06 '17 at 14:51
  • Possible duplicate of [dict.fromkeys all point to same list](https://stackoverflow.com/questions/15516413/dict-fromkeys-all-point-to-same-list) – cs95 Jul 06 '17 at 14:55
  • i actually had it, but the answer it already posted so no need anymore @cᴏʟᴅsᴘᴇᴇᴅ – Rayhane Mama Jul 06 '17 at 14:55

1 Answers1

1

It looks like they have same memory address, so modifying one modifies them all, and this is because they are a only reference.

Here is a better explanation:

Your first line creates your object with integers keys and empty object as a value for all of them.

yeartonametolist = dict.fromkeys(range(2007,2017),{})

Now at this point, if you use the id() function like this

id(yeartonametolist[2016]) #4294024972L
id(yeartonametolist[2015]) #4294024972L

It is the same id, so if you do

yeartonametolist[2007]["a"] = 1
yeartonametolist[2008]["b"] = 2

you are changing the same object.

You can see it as well if you change the {} to object()

test = dict.fromkeys(range(2007,2017), object() )
print test

Output:

{
 2016: <object object at 0xfff964d8>, 
 2007: <object object at 0xfff964d8>, 
 2008: <object object at 0xfff964d8>, 
 2009: <object object at 0xfff964d8>, 
 2010: <object object at 0xfff964d8>, 
 2011: <object object at 0xfff964d8>, 
 2012: <object object at 0xfff964d8>,
 2013: <object object at 0xfff964d8>, 
 2014: <object object at 0xfff964d8>, 
 2015: <object object at 0xfff964d8>
}

The value for each key points to the same memory address.

mugabits
  • 1,015
  • 1
  • 12
  • 22