Can't understand python shallow copy when working with int and str
Python doc about copy
The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):
A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original. A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
I think shallow copy should copy the reference of the list, so update the shallow_copy_list should also change the original list, but the first example doesn't work as expected.
Python 3.6.0 (default, Dec 24 2016, 08:01:42) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
items = [1, 2, 3, 4, 5, 6]
items_copy = items[:]
items_copy[0] = 'a'
items_copy == items
False
I think this is a shallow copy, and items_copy == items should return True but it's False. But another example return True
items = [{'id': 1, 'name': 'laptop', 'value': 1000}, {'id': 2, 'name': 'chair', 'value': 300},]
items_copy = items[:]
items_copy[0]['id'] = 'a'
items_copy == items
True
References:
Python Shallow and deep copies
Ned Batchelder - Facts and Myths about Python names and values - PyCon 2015
As far as I know: Shallow copying means the content of the dictionary is not copied by value
, but creating a new reference.
Have a look at this example.
items = [{'id': 1, 'name': 'laptop', 'value': 1000}, {'id': 2, 'name': 'chair', 'value': 300},]
items_copy = items[:]
items_copy[0]['id'] = 'a'
print items_copy,id(items_copy),items,id(items)
print items_copy == items
Output:
[{'id': 'a', 'value': 1000, 'name': 'laptop'}, {'id': 2, 'value': 300, 'name': 'chair'}] 4455943200 [{'id': 'a', 'value': 1000, 'name': 'laptop'}, {'id': 2, 'value': 300, 'name': 'chair'}] 4455866312
True
items = [{'id': 1, 'name': 'laptop', 'value': 1000}, {'id': 2, 'name': 'chair', 'value': 300},]
items_copy = items[:]
items_copy[0]= 'a'
print items_copy,id(items_copy),items,id(items)
print items_copy == items
Output:
['a', {'id': 2, 'value': 300, 'name': 'chair'}] 4455943200 [{'id': 'a', 'value': 1000, 'name': 'laptop'}, {'id': 2, 'value': 300, 'name': 'chair'}] 4455866312
False
This code:
items_copy[0] = 'a'
Means "replace the item in items_copy[0]
with a
. It changes the object referred to by items_copy
(and therefore changes all other variables that refer to that object, which in this case does not include items
), but has no effect at all on the item that was previously in items_copy[0]
(in this the dictionary).
This is similar to this sequence of events:
foo = {'id': 1, 'name': 'laptop', 'value': 1000}
bar = foo
foo = 'a'
foo == bar
This would return False
, because bar
is still the (unchanged) dictionary object.
In the second case, you did not modify either list, but you did modify the (first) dictionary that is referred to by both copies, similar to this sequence:
foo = {'id': 1, 'name': 'laptop', 'value': 1000}
bar = foo
foo['id'] = 'a'
foo == bar
This would return True
. (This is slightly different from your second example because in this case foo
and bar
are not only equal but actually refer to the same object.)
上一篇: 我如何并行化一个简单的Python循环?