Hi all, Clay Culver wrote:
Stefan Seefeld wrote:
Python:
d = dict(x.__dict__) # copies x.__dict__ d['whatever'] # modifies the copy
"
This is confusing. May be I'm reading the above not correctly, but in my interpretation 'making a copy' means making a deep copy, and 'modifies the copy' implies the original is unchanged. However:
class A: ... def foo(self): return 42 ... d = A.__dict__ print id(d), id(A.__dict__) -1208268764 -1208268764
Following the code above that though:
class A: ... def foo(self): ... return 42 ... d = dict( A.__dict__ ) print id(d), id( A.__dict__ ) 10356464 10357184
Which is a deep copy.
The C++ doesn't seem to do the same thing when you pass a value into dict( ).
In Python we got two types of copies, deep and shallow. A shallow copy of a container creates a new container, but the items are still the same. Changing the container itself doesn't affect the original, but changing one of the items does. Consider:
class C: pass ... c = C() c.x = 1 a = [c] b = list(a) a [<__main__.C instance at 0x009D9C10>] b [<__main__.C instance at 0x009D9C10>] a.append(1) a [<__main__.C instance at 0x009D9C10>, 1] b [<__main__.C instance at 0x009D9C10>] a[0].x = 4 b[0].x 4
Note that "list(seq)" creates a shallow copy of "seq", ie, its a different list, but with the same elements (on a side note, "copy" from the copy module provides a shallow copy operation). That's why appending something to "a" doesn't change "b", but changing C's instance does, because both lists point to the same object. This confusion is common in C++ programmers, because variables in C++ have value semantics, while in Python variables are only bindings to objects. To make it clear what is a binding, think of it as a pointer:
c.x 4 d = c d.x = 10 c.x 10
The line "d = c" doesn't make any copies. Instead, now the *binding* d points to the same object as "c", exactly as if both were pointers. For completeness sake, here is an example of a deep copy, which copies not only the container, but all the elements inside the container recursively:
import copy c.x = 4 a = [c] b = copy.deepcopy(a) a[0].x = 0 b[0].x 4
As you can see, now a deep copy is being made: both the lists and elements are being copied. Hope that clears it up! Regards, Nicodemus.