[C++-sig] Multiple python interpreter contexts
Nicodemus
nicodemus at esss.com.br
Wed Feb 23 00:10:28 CET 2005
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.
More information about the Cplusplus-sig
mailing list