1.变量的赋值操作
只是形成两个变量,实际上还是指向同一个对象
【1】在Python中,当你执行赋值操作,例如 a = [1, 2, 3]
然后 b = a
,你并没有创建两个独立的对象。实际上,变量 a
和 b
都指向了内存中的同一个列表对象 [1, 2, 3]
。
1
2
3
4
a = [1, 2, 3]
b = a
print(a, id(a))
print(b, id(b))
【2】修改其中一个变量: 如果你通过 b
修改了列表,你会发现 a
也会受到影响,因为它们引用的是同一个底层数据。
1
2
3
4
5
6
7
a = [1, 2, 3]
b = a
print(a, id(a))
print(b, id(b))
b[0] = 100
print(a)
print(b)
2.浅拷贝(只拷贝顶层对象,子对象共享)
Python拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝,因此,源对象与拷贝对象会引用同一个子对象
浅拷贝创建一个新对象,但新对象中包含的子对象(如果存在的话)仍然是原始对象的引用。这意味着,如果你修改了子对象,原始对象和拷贝对象都会受到影响。
在Python中,实现浅拷贝有几种常见的方法:
【1】切片操作 [:]
: 对于列表、元组等序列类型,使用切片 [:]
可以创建一个浅拷贝。
1
2
3
4
5
6
7
8
9
10
original_list = [[1, 2], 3]
shallow_copied_list = original_list[:] # 切片实现浅拷贝
print(id(original_list))
print(id(shallow_copied_list))
print(id(original_list[0]))
print(id(shallow_copied_list[0])) # 子对象共享
# 修改子列表
shallow_copied_list[0].append(90)
print(original_list)
print(shallow_copied_list)
【2】list()
构造函数: 使用 list()
构造函数也可以创建一个列表的浅拷贝。
1
2
3
4
5
6
print("\n", "-"*40, "\n")
l1 = [["Hello"], "World"]
l2 = list(l1)
print(l1, l2)
print(id(l1), id(l2))
print(id(l1[0]), id(l2[0]))
【3】copy()
模块的 copy()
函数: 对于更复杂的对象,可以使用 copy
模块的 copy()
函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class CPU:
pass
class Disk:
pass
class Computer:
def __init__(self, cpu, disk):
self.cpu = cpu
self.disk = disk
import copy
c1 = Computer(CPU(), Disk())
print(c1, id(c1), id(c1.cpu), id(c1.disk))
c2 = copy.copy(c1)
print(c2, id(c2), id(c2.cpu), id(c2.disk))
3.深拷贝
使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class CPU:
pass
class Disk:
pass
class Computer:
def __init__(self, cpu, disk):
self.cpu = cpu
self.disk = disk
import copy
c1 = Computer(CPU(), Disk())
print(c1, id(c1), id(c1.cpu), id(c1.disk))
c2 = copy.deepcopy(c1)
print(c2, id(c2), id(c2.cpu), id(c2.disk))