I have a friend struggling with some code wight now, so I’m copy-pasting an interactive session with some object reference basics that I hope will clarify some things 😉
There’s also a pastie for this in http://paste.lisp.org/+2E0W for easier reading.
>>> # First, lets make a Class to help with tests >>> class Coco(object): def __init__(self, value=0): self.value = value >>> # Lets make a list of instances, the dumb way >>> a = [Coco()] * 4 >>> a [<__main__.Coco object at 0xb64c9cac>, <__main__.Coco object at 0xb64c9cac>, <__main__.Coco object at 0xb64c9cac>, <__main__.Coco object at 0xb64c9cac>] >>> # See that the addresses are the same? Lets look values >>> [i.value for i in a] [0, 0, 0, 0] >>> # Now, let's try to change one of them >>> a[0].value = 1 >>> # We now expect [1, 0, 0, 0], right? >>> [i.value for i in a] [1, 1, 1, 1] >>> # NOPE! All of them changed because it's THE SAME OBJECT >>> >>> # Let's do it again the smart way >>> a = [] >>> for i in range(4): a.append(Coco()) >>> a [<__main__.Coco object at 0xb64b906c>, <__main__.Coco object at 0xb64d128c>, <__main__.Coco object at 0xb64d1c2c>, <__main__.Coco object at 0xb64d1c0c>] >>> # See that the addresses are different? >>> [i.value for i in a] [0, 0, 0, 0] >>> a[0].value = 1 >>> [i.value for i in a] [1, 0, 0, 0] >>> # Pretty cool huh? >>> >>> # Lets also put the list in variable b >>> b = a >>> [i.value for i in a] [1, 0, 0, 0] >>> [i.value for i in b] [1, 0, 0, 0] >>> # And change a value in b >>> b[0].value = 0 >>> [i.value for i in b] [0, 0, 0, 0] >>> [i.value for i in a] [0, 0, 0, 0] >>> # a and b are the same object. A no brainer! >>> >>> # Now let's copy once with copy() and once with deepcopy() >>> from copy import copy, deepcopy >>> a_copy = copy(a) # You can also do =a[:] for lists and =a.copy() for dicts >>> a_deepcopy = deepcopy(a) >>> a [<__main__.Coco object at 0xb64b906c>, <__main__.Coco object at 0xb64d128c>, <__main__.Coco object at 0xb64d1c2c>, <__main__.Coco object at 0xb64d1c0c>] >>> a_copy [<__main__.Coco object at 0xb64b906c>, <__main__.Coco object at 0xb64d128c>, <__main__.Coco object at 0xb64d1c2c>, <__main__.Coco object at 0xb64d1c0c>] >>> a_deepcopy [<__main__.Coco object at 0xb64d1a4c>, <__main__.Coco object at 0xb64d1a2c>, <__main__.Coco object at 0xb64d1a0c>, <__main__.Coco object at 0xb64d19ec>] >>> a_copy[0].value = 4 >>> a_deepcopy[1].value = 6 >>> # Can you foretell what will happen now? >>> [i.value for i in a_copy] [4, 0, 0, 0] >>> [i.value for i in a_deepcopy] [0, 6, 0, 0] >>> [i.value for i in a] [4, 0, 0, 0] >>> # While a and a_copy are not the same, their contents are shared! >>> # Here's how to try when in doubt >>> a is b True >>> a is a_copy False >>> a[0] is a_copy[0] True >>> a[0] is a_deepcopy[0] False >>> >>> # PS. If you make a list the dumb way >>> a = [Coco()] * 4 >>> # ..you'll have a list of the same objects even after a deepcopy >>> k = [Coco()] * 4 >>> k_deepcopy = deepcopy(k) >>> k_deepcopy[0].value = 1 >>> [i.value for i in k_deepcopy] [1, 1, 1, 1] >>> k_deepcopy[0] is k_deepcopy[3] True >>> # ..although, not the same ones as the originals >>> [i.value for i in k] [0, 0, 0, 0] >>> k_deepcopy[0] is k[0] False >>> >>> # Hope that's helpful ;) >>>
Nick