在Python中,深拷贝和浅拷贝是指复制对象的方式,其中的差别主要在于是否复制了对象中的子对象。
浅拷贝
在Python中,浅拷贝是创建一个新对象,然后复制原对象的引用对象到新对象上。对于原对象中的可变对象(例如列表或字典),新对象和原对象将共享此对象。如果你更改可变对象中的值,那么这个改变将在所有的拷贝对象中体现。
这里是一个例子:
import copy
original_list = [[1, 2, 3], [4, 5, 6]]
shallow_copied_list = copy.copy(original_list)
shallow_copied_list[0][1] = 'X'
print(original_list) # 输出: [[1, 'X', 3], [4, 5, 6]]
print(shallow_copied_list) # 输出: [[1, 'X', 3], [4, 5, 6]]
在这个例子中,shallow_copied_list是original_list的浅拷贝。当我们修改了shallow_copied_list中的一个元素时,original_list也会发生相应的改变。
深拷贝
与浅拷贝相反,深拷贝是创建一个新对象,并递归复制原对象中的所有元素及其子元素。因此,对于原对象中的可变对象,新对象将有自己的副本。如果你更改新对象中的可变对象的值,原对象中的相应值将不会改变。
这里是一个例子:
import copy
original_list = [[1, 2, 3], [4, 5, 6]]
deep_copied_list = copy.deepcopy(original_list)
deep_copied_list[0][1] = 'X'
print(original_list) # 输出: [[1, 2, 3], [4, 5, 6]]
print(deep_copied_list) # 输出: [[1, 'X', 3], [4, 5, 6]]
在这个例子中,deep_copied_list是original_list的深拷贝。当我们修改了deep_copied_list中的一个元素时,original_list没有发生改变,这是因为在深拷贝过程中,复制了所有的子对象。
请注意,深拷贝和浅拷贝的概念主要应用于复合对象(如列表,字典,类实例等)。对于简单的不可变对象(如整数,字符串,元组等),深拷贝和浅拷贝没有差异,因为它们的值不能被改变。
python中浅拷贝的方式
1、使用内置的 copy 模块中的 copy() 函数:
import copy
list1 = [1, 2, 3]
list2 = copy.copy(list1)
2、切片操作,这在列表中特别常用:
list1 = [1, 2, 3]
list2 = list1[:]
3、使用列表的 copy() 方法:
list1 = [1, 2, 3]
list2 = list1.copy()
4、使用字典的 copy() 方法(针对字典):
dict1 = {'a': 1, 'b': 2, 'c': 3}
dict2 = dict1.copy()
5、使用 list() 和 dict() 函数转换(仅适用于列表和字典):
list1 = [1, 2, 3]
list2 = list(list1)
dict1 = {'a': 1, 'b': 2, 'c': 3}
dict2 = dict(dict1)
以上这些方法都是浅拷贝,意味着如果你在原列表或字典中存储了子对象(例如列表或字典),则新列表或字典将共享这些子对象,而不是创建新的子对象。如果你修改了子对象的值,那么这个改变将在所有的拷贝对象中体现。
补充
Python中的赋值操作(=)实际上并不创建任何原对象的拷贝。赋值操作只是创建了一个新的引用,这个新引用指向原对象。这意味着原对象和新引用都指向同一内存中的数据。
在Python中,所有的变量都只是对对象的引用,而不是实际的数据。当你使用赋值操作时,你只是在创建一个新的引用,而不是复制对象。
例如:
list1 = [1, 2, 3]
list2 = list1
在这个例子中,list1 和 list2 都引用同一个列表对象 [1, 2, 3]。如果你修改了 list1 或 list2,那么这个改变将在两个引用中都体现。
例如:
list1 = [1, 2, 3]
list2 = list1
list2.append(4)
print(list1) # 输出: [1, 2, 3, 4]
print(list2) # 输出: [1, 2, 3, 4]
在这个例子中,当我们通过 list2 添加一个新元素到列表中时,我们可以看到,list1 也发生了改变,这是因为 list1 和 list2 都指向同一个列表对象。
另外,对于一些自定义对象,如果你想实现深拷贝,你可能需要在自己的类中实现特殊方法 deepcopy(),这个方法告诉 copy.deepcopy() 如何进行深拷贝。具体实现方式取决于你的对象的具体结构和需求。
以下是一个例子,它演示了如何在一个简单的类中实现 deepcopy() 方法:
import copy
class MyClass:
def __init__(self, value):
self.value = value
self.child = None
def __deepcopy__(self, memo):
# 创建一个新的 MyClass 实例
new_copy = MyClass(self.value)
# 添加已复制对象的引用到 memo 字典,避免无限递归
memo[id(self)] = new_copy
# 复制子对象
new_copy.child = copy.deepcopy(self.child, memo)
return new_copy
# 创建 MyClass 对象并设置子对象
obj1 = MyClass(1)
obj2 = MyClass(2)
obj1.child = obj2
# 创建深拷贝
obj1_copy = copy.deepcopy(obj1)
# 改变深拷贝的值并检查原对象
obj1_copy.child.value = 3
print(obj1.child.value) # 输出: 2
在这个例子中,MyClass 类中的 deepcopy() 方法创建了一个新的 MyClass 实例,并复制了 value 属性。然后,它使用 copy.deepcopy() 函数来复制 child 属性,创建了一个新的 MyClass 对象,该对象具有与原始 child 对象相同的 value 值。通过这种方式,我们可以确保 child 属性是深拷贝的。
注意 memo 参数的使用。这是一个字典,用于记录已经复制过的对象,以防止无限递归(例如,当一个对象通过某种方式间接引用自己时)。你需要在 deepcopy() 方法中使用 memo 字典来跟踪已复制的对象。
在这个例子中,当我们修改了复制后的对象的 child 的 value 属性时,原对象的对应属性没有发生改变,说明我们成功地实现了深拷贝。