[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