Frage

consider the following code

#! /usr/bin/env python

my_dict = {1:['Bernd','das','Brot'], 2:['Chili','das','Schaf'], 3:['Briegel','der','Busch']}
print my_dict

chili = my_dict[2]
print chili

del chili[2]
print chili
print my_dict

which produces the following output with my Python 2.7.5:

{1: ['Bernd', 'das', 'Brot'], 2: ['Chili', 'das', 'Schaf'], 3: ['Briegel', 'der', 'Busch']}
['Chili', 'das']
{1: ['Bernd', 'das', 'Brot'], 2: ['Chili', 'das'], 3: ['Briegel', 'der', 'Busch']}

As you can see, the list in the dict was also manipulated, so they appear to point to the same object/thing in memory.

Maybe I understand a basic Python principle wrong here (feel free to flame & point me towards the spec), but is this intended behaviour? And if it is, is there a way to delete and entry by index from a list taken from a dict without manipulating the original dict? Quite often I find out there is already an extraordinary simple Python way for doing stuff I try to accomplish with complicated code constructs.

I have a large dict here and I take lists out of it quite often, and I don't want to rebuild the dict each time I process the list in any way.

Thank you very much for your time & help,

Tobias

War es hilfreich?

Lösung

Yes, this is intended behaviour. Python names and entries in dictionaries and lists are mere references to the actual objects, stored in a big pile (the heap) in memory.

Thus, my_dict[2] and chili both refer to the same list object, and list objects are mutable. Deleting an entry from a list object means that all references to that object see the change.

If you want chili to not be the same list object, you must create a copy. You can create a shallow copy with either:

chili = my_dict[2][:]

as slicing from first to last index produces a new list object, or using:

chili = list(my_dict[2])

which produces a new list object, copying all references stored in the original sequence.

These create shallow copies; if anything in my_dict[2] is itself mutable you would still be manipulating an object shared between the chili list and the my_dict[2] list.

You can create a deep copy by using the copy.deepcopy() function, which recursively produces copies of objects.

Andere Tipps

When you write:

 chili = my_dict[2]

Then chili is a reference to the same object as my_dict[2]. So modifying chili will modify my_dict.

You can copy a list:

  chili = list(my_dict[2])

Now del chili[2] won't modify my_dict.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top