Python3的深拷贝与浅拷贝

1. 可变类型与不可变类型

在理解深拷贝和前拷贝之前,首先要了解python的可变类型和不可变类型:

  • 可变类型:list、dict
  • 不可变类型:number、str、bool、tuple

python中的不可变数据类型,不允许变量的值 原地 发生变化,一但值发生了变化,则相当于新建了一个对象,id会变。
所以,可变类型:值变化,id不变化;不可变类型:值变化,id变化。

2. 指向

  • 变量 = xx 时,认为该变量指向了xx的内存空间
>>> a = [11, 22]
>>> a
[11, 22]
>>> id(a)
4484053312
>>> b = a
>>> b
[11, 22]
>>> id(b)
4484053312

在这里插入图片描述

  • 若xx为可变类型,如列表,对其使用append、insert等方法进行改变时,指向的变量一同发生变化
>>> a.append(33)
>>> a
[11, 22, 33]
>>> b
[11, 22, 33]

3. 浅拷贝

  • 浅拷贝是对于一个对象的顶层拷贝,只拷贝引用,不拷贝内容
>>> a = [11, 22]
>>> b = [33, 44]
>>> c = [a, b]
>>> d = copy.copy(c)
>>> id(c)
4488961088
>>> id(d)
4488881664

在这里插入图片描述

  • 当对其中的内容进行更改时,指向的变量一同发生变化
>>> a.append(55)
>>> c
[[11, 22, 55], [33, 44]]
>>> d
[[11, 22, 55], [33, 44]]

注意1:分片表达式相当于浅拷贝

>>> f = c[:]
>>> id(f)
4488900032
>>> f
[[11, 22, 55], [33, 44]]
>>> b.append(66)
>>> c
[[11, 22, 55], [33, 44, 66]]
>>> f
[[11, 22, 55], [33, 44, 66]]

注意2:字典的copy()方法相当于浅拷贝

>>> a = {"name": "zhangsan", "age": 9, "like": ["pingpang", "swim"]}
>>> b = a.copy()
>>> id(a)
4488873984
>>> id(b)
4488978816
>>> a["like"].append("run")
>>> a
{'name': 'zhangsan', 'age': 9, 'like': ['pingpang', 'swim', 'run']}
>>> b
{'name': 'zhangsan', 'age': 9, 'like': ['pingpang', 'swim', 'run']}

注意3:若对一个全为不可变类型的数据进行浅拷贝,则相当于指向

>>> a = (11, 22)
>>> b = (33, 44)
>>> c = (a, b)
>>> d = copy.copy(c)
>>> c
((11, 22), (33, 44))
>>> id(c)
4488956736
>>> id(d)
4488956736

注意4:若对一个含有可变类型的数据进行浅拷贝,则同样相当于指向

>>> a = [11, 22]
>>> b = (33, 44)
>>> c = (a, b)
>>> d = copy.copy(c)
>>> id(c)
4489272320
>>> id(d)
4489272320
>>> a.append(55)
>>> c
([11, 22, 55], (33, 44))
>>> d
([11, 22, 55], (33, 44))

4. 深拷贝

  • 深拷贝是对于一个对象所有层次的拷贝(递归)
>>> a = [11, 22]
>>> b = [33, 44]
>>> c = [a, b]
>>> d = copy.deepcopy(c)
>>> id(c)
4488971648
>>> id(d)
4488980032
>>> c
[[11, 22], [33, 44]]
>>> a.append(55)
>>> c
[[11, 22, 55], [33, 44]]
>>> d
[[11, 22], [33, 44]]

注意1:若对一个全为不可变类型的数据进行深拷贝,则相当于指向

>>> a = (11, 22)
>>> b = (33, 44)
>>> c = (a, b)
>>> d = copy.deepcopy(c)
>>> c
((11, 22), (33, 44))
>>> id(c)
4488898752
>>> id(d)
4488898752

注意2:若对一个含有可变类型的数据进行深拷贝,则递归拷贝

>>> a = [11, 22]
>>> b = (33, 44)
>>> c = (a, b)
>>> d = copy.deepcopy(c)
>>> id(c)
4484150272
>>> id(d)
4486546880
>>> a.append(55)
>>> c
([11, 22, 55], (33, 44))
>>> d
([11, 22], (33, 44))

5. 深拷贝在传参中的应用

  • 传参时使用深拷贝方法,避免可变类型变量被函数修改,污染变量
import copy


def test_nums(temp):
    temp.append(33)


nums = [11, 22]
test_nums(nums)
print(nums)
# [11, 22, 33]

test_nums(copy.deepcopy(nums))
print(nums)
# [11, 22, 33]

test_nums(nums)
print(nums)
# [11, 22, 33, 33]

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>