一文说清楚python中的深拷贝和浅拷贝

在这里插入图片描述

在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 属性时,原对象的对应属性没有发生改变,说明我们成功地实现了深拷贝。

引用

图解深浅拷贝

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值