今天看到一道Python深拷贝、浅拷贝的练习题,下面我们来详细解释一下。练习题如下:
import copy
a = [1, 2, 3, 4, ['a', 'b']]
b = a
print(id(a), id(b), a is b)
c = copy.copy(a)
print(id(a), id(c), a is c)
d = copy.deepcopy(a)
print(id(a), id(d), a is d)
a.append(5)
a[4].append('c')
print('a:', a)
print('b:', b)
print('c:', c)
print('d:', d)
最后a、b、c、d 值如下:
a: [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b: [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c: [1, 2, 3, 4, ['a', 'b', 'c']]
d: [1, 2, 3, 4, ['a', 'b']]
首先,我们需要理解Python中的浅拷贝和深拷贝。
- 浅拷贝:创建一个新的列表,并将原列表中的元素(如果它们是标量类型,如整数、浮点数、字符串等)复制到新列表中。但如果元素是复合类型(如列表、字典等),则只复制其引用,而不是内容。
- 深拷贝:创建一个新的列表,并将原列表中的元素(无论是标量类型还是复合类型)都完全复制到新列表中。
接下来,我们根据题目给出的代码进行逐行解释:
a = [1, 2, 3, 4, ['a', 'b']]
这里我们定义了一个名为a
的列表,它包含整数和子列表。
b = a
这行代码创建了一个新的变量b
,并将其设置为与a
相同的引用。此时,a
和b
都指向同一个列表。所以a和b的id是一样的。
c = copy.copy(a)
使用copy.copy()
方法对a
进行浅拷贝。浅拷贝是创建一个新的列表,并将原列表中的元素复制到新列表中。但如果元素是复合类型(如列表、字典等),则只复制其引用,而不是内容。所以 c 和 a 的 id 是不同的。
d = copy.deepcopy(a)
使用copy.deepcopy()
方法对a
进行深拷贝,并将结果赋值给变量d
。此时,只有d
是原始列表的一个完全独立的副本。
a.append(5)
a
本身被修改,添加了元素5。- 由于
b
和a
指向同一个列表,所以b
也“看到”了添加的元素5。 c
是a
的一个浅拷贝,但它有自己的内存地址。因此,对a
的修改(使用append
方法)不会影响c
。d
是a
的深拷贝,所以它是一个完全独立的副本。对a
的任何修改都不会影响d
。
a[4].append('c')
这行代码向列表a
的最后一个元素(子列表)添加了一个新元素'c'。由于这是一个复合类型的修改,这会修改到所有引用该子列表的对象。因此,现在a
、b
和c
的最后一个元素都是['a', 'b', 'c'],而只有d
不受影响。