Python高级编程(10):深拷贝与浅拷贝

一、深拷贝和浅拷贝概念

  • 浅拷贝重新分配一块内存创建一个新的对象,拷贝父对象,不会拷贝对象内部的子对象。
  • 深拷贝重新分配一块内存创建一个新的对象,完全拷贝父对象和子对象,新对象和原对象没有任何关联

1.1 简单来说:

  • 浅拷贝只复制某个对象的引用,而不复制对象本身,新旧对象还是共享同一块内存。
  • 深拷贝会创造一个一模一样的对象,新对象和原对象不共享内存,修改新对象不会改变原对象。

1.2 深浅拷贝优缺点:

  • 浅拷贝耗时短,占用内存空间少。
  • 深拷贝耗时长,且占用内存空间。

二、浅拷贝

2.1 只有一层数据类型,且为可变数据类型,如列表、字典。

"""
只有一层数据类型,且为可变数据类型,
浅拷贝后会创建一个新的内存地址
"""

from copy import copy

l1 = [1, 2, 3, 4]
l2 = copy(l1)

print(id(l1))  # 34653376
print(id(l2))  # 35040256

l1.append(5)
l2.append(6)
print(l1)  # [1, 2, 3, 4, 5]
print(l2)  # [1, 2, 3, 4, 6]

2.2 只有一层数据类型,且为不可变数据类型

"""
只有一层数据类型,且为不可变数据类型,
浅拷贝后内存地址不变
"""

from copy import copy

l1 = "1234"
l2 = copy(l1)

print(id(l1))  # 38998256
print(id(l2))  # 38998256

2.3 有两层数据类型,外层为可变数据类型,内层包含可变数据类型元素

"""
有两层数据类型,外层为可变数据类型,内层包含可变数据类型
浅拷贝后外层地址改变,内层地址不变
"""

from copy import copy

l1 = [1, 2, 3, 4, [100, 200]]

l2 = copy(l1)

print(id(l1))  # 40283008
print(id(l2))  # 40440768

print(id(l1[4]))  # 39306240
print(id(l2[4]))  # 39306240
                  # 内层地址不变可以减少内存地址开销

l1[4].append(300)
print(l1)  # [1, 2, 3, 4, [100, 200, 300]]
print(l2)  # [1, 2, 3, 4, [100, 200, 300]]
           # 使用浅拷贝,如果元素中存在可变类型数据,
           # 内层的子列表不会发生拷贝,所以子列表发生变化,对应拷贝后的列表也发生变化

三、深拷贝

3.1 只有一层数据类型,且为可变数据类型,如列表、字典。

"""
只有一层数据类型,且为可变数据类型,
深拷贝后会创建一个新的内存地址
"""

from copy import deepcopy

l1 = [1, 2, 3, 4]

l2 = deepcopy(l1)

print(id(l1))  # 39371840
print(id(l2))  # 40086400

l1.append(5)
l2.append(6)
print(l1)  # [1, 2, 3, 4, 5]
print(l2)  # [1, 2, 3, 4, 6]

3.2 只有一层数据类型,且为不可变数据类型

"""
只有一层数据类型,且为不可变数据类型,
深拷贝后内存地址不变
"""

from copy import deepcopy

l1 = "1234"

l2 = deepcopy(l1)

print(id(l1))  # 34544432
print(id(l2))  # 34544432

3.3 有两层数据类型,外层为可变数据类型,内层包含可变数据类型元素

"""
有两层数据类型,外层为可变数据类型,内层包含可变数据类型
深拷贝后外层地址改变,内层地址改变
"""

from copy import deepcopy

l1 = [1, 2, 3, 4, [100, 200]]

l2 = deepcopy(l1)

print(id(l1))  # 40217536
print(id(l2))  # 40375296

print(id(l1[4]))  # 39502976
print(id(l2[4]))  # 39152832
                  # 深拷贝后外层地址改变

l1[4].append(300)
print(l1)  # [1, 2, 3, 4, [100, 200, 300]]
print(l2)  # [1, 2, 3, 4, [100, 200]]
           # 使用深拷贝,如果元素中存在可变类型数据,
           # 内层的子列表也发生拷贝,子列表变化,拷贝后的列表不会变化

3.4 有两层数据类型,外层为可变数据类型,内层包含不可变数据类型元素 

"""
有两层数据类型,外层为可变数据类型,
内层不可变数据类型的元素,深拷贝不改变内层地址,
内层是可变数据类型的元素,深拷贝改变内层地址
"""

from copy import deepcopy

l1 = [1, 2, 3, [100, 200], "1121"]

l2 = deepcopy(l1)

# 外层是可变数据类型,深拷贝,外层地址改变
print(id(l1))  # 40152000
print(id(l2))  # 40301888

# 内层是可变数据类型的元素,深拷贝,该元素对应的内层地址发生改变
print(id(l1[3]))  # 39437504
print(id(l2[3]))  # 39438144

# 内层是不可变数据类型的元素,深拷贝,该元素对应的内层地址不变
print(id(l1[4]))  # 39066416
print(id(l2[4]))  # 39066416

四、深拷贝和浅拷贝总结

  • 浅拷贝只有外层是可变数据类型时,才能改变外层地址。内层地址无论是否是可变数据类型,都不会改变内层地址。所以,浅拷贝不会拷贝子列表,子列表发生变化对应的拷贝后的数据也会发生变化。
  • 深拷贝内层是可变数据类型时,内外层地址均发生改变。内层不可变数据类型的元素,深拷贝后对应元素处的内层地址不会改变。所以,深拷贝会拷贝子列表,子列表发生变化对应的拷贝后的数据不会发生变化。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 深拷贝浅拷贝都是对象复制的方式,深拷贝会创建一个新的对象,复制对象中所有的值和数据,而不是只复制引用,因此新对象和原对象是完全独立的。浅拷贝则只是复制对象的引用,因此新对象和原对象共享相同的数据,对新对象或原对象的更改都会影响到另一个对象。 ### 回答2: 深拷贝浅拷贝是在编程中常用的两种复制对象的方式。 浅拷贝是创建一个新的对象,新对象的属性值是原对象的引用。即新旧对象公用同一份数据,任何一方对对象内容的修改都会影响另一方。浅拷贝能够更快地创建一个对象,因为它只需复制对象的引用而非内容。在Python中,可以使用copy()方法来进行浅拷贝深拷贝是创建一个新的对象,新对象和原对象的属性值是完全独立的。即无论任何一方对对象内容的修改,不会影响另一方。深拷贝复制的是对象的内容,而不是引用。由于深拷贝需要复制所有的内容,因此相对于浅拷贝而言,它的速度较慢。在Python中,可以使用deepcopy()方法来进行深拷贝深拷贝适用于需要独立操作的情况,例如对于可变对象(如列表、字典),深拷贝可以确保对新对象的修改不会影响原对象。而浅拷贝适用于不需要独立操作的情况,例如对于不可变对象(如整数、字符串),浅拷贝已经足够满足需求。 需要注意的是,对于包含多层嵌套对象的复制,浅拷贝只会复制最外层的对象引用,而深拷贝会递归复制所有层级的对象内容。因此,如果原对象中存在嵌套的可变对象,使用浅拷贝可能会导致一些意料之外的结果,而深拷贝可以避免这个问题。 ### 回答3: 深拷贝浅拷贝是在编程中常用的两个概念,用于描述数据拷贝的方式。 浅拷贝是指当我们将一个对象进行拷贝时,只是拷贝了对象的引用,而不是拷贝对象本身。这意味着新对象和原对象共享同一块内存空间,对其中一个对象进行修改会影响到另一个对象。在浅拷贝中,只有对象的第一层属性被复制,对于嵌套的对象或子对象,依然是引用关系。 而深拷贝则是将对象的所有层级都进行复制,从而得到一个全新的对象。这意味着任何对原对象的修改都不会影响到新对象,因为它们在内存中保存在不同的位置。在深拷贝中,所有的属性和子属性都被复制,并且也被认为是独立的对象。 浅拷贝的优点是效率高,因为它只复制了引用,而不需要复制整个对象的内容。然而,它的缺点是容易造成数据的不一致性,因为对其中一个对象的修改会影响到其他对象。 深拷贝的优点是能够完整地复制对象及其嵌套的属性和子属性,确保数据的一致性。然而,由于要复制整个对象的内容,所以相比浅拷贝会消耗更多的内存和时间。 在选择使用深拷贝浅拷贝时,需要根据实际情况进行权衡。如果需要保证数据的一致性并且不担心性能问题,使用深拷贝是较好的选择。如果对性能要求较高,而且可以接受数据的不一致性,浅拷贝可能更适合。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值