Python - 浅深拷贝

数据副本的生成就会产生数据拷贝,在 Python 中数据拷贝涉及到对象、可变类型、引用

对象
在 Python 中,一切皆对象。所有 Python 对象都拥有三个属性:身份(id)、类型(type)、值(value)。

str = "Hello Pyhton"	# str 对象。
print(id(str))	# id:身份的唯一标识。
print(type(str))	# type:对象的类型,决定了该对象可以保存什么类型的值。
print(str)	# 打印 str 对象的值。

# 执行结果
2850825703984	# id
<class 'str'>	# type
Hello Pyhton	# value

可变与不可变对象
在 Python 中,按更新对象的方式,对象分为可变对象与不可变对象:
不可变对象:对象的值和 id 都不可变。不可变对象的数据类型有数字、字符串、元组、bool。
可变对象:对象的值可变,id 不变。可变对象的数据类型有列表、字典、集合。

引用
在 Python 程序中,每个对象都会在内存中申请开辟一块空间来保存该对象,该对象在内存中所在位置的地址被称为引用。在开发程序时,所定义的变量名实际就对象的地址引用。
引用,实际就是内存中的一个数字地址编号,在使用对象时,只要知道这个对象的地址,就可以操作这个对象,但是因为这个数字地址不方便在开发时使用和记忆,所以使用变量名的形式来代替对象的数字地址。 在 Python 中,变量就是地址的一种表示形式,并不开辟存储空间。
总结:引用对开发人员来讲就是变量名,对内存来讲就是一串数字地址编号。

str = "Hello Pyhton"
print(id(str))
print(id("Hello Pyhton"))

# 执行结果
2124739974192
2124739974192

引用赋值
赋值的本质就是让多个变量同时引用同一个对象的地址。

  • 不可变对象的引用赋值
    对不可变对象赋值,实际就是在内存中开辟一片空间指向新的对象,原不可变对象不会被修改。

案例理解:
a 与 b 在内存中都是指向 1 的引用,所以 a、b 的引用是相同的。

a = 1
b = a
print(a,id(a))
print(b,id(b))

# 执行结果
1 140703586050896
1 140703586050896

现在再给 a 重新赋值,可以看出当给 a 赋新的对象时,将指向新的引用,不在指向旧的对象引用。

a = 2
print(a,id(a))
print(b,id(b))

# 执行结果
2 140703586050928
1 140703586050896
  • 可变对象的引用赋值
    可变对象保存的并不是真正的对象数据,而是对象的引用。当对可变对象进行赋值时,只是将可变对象中保存的引用指向了新的对象。

当改变 list1 时,整个列表的引用会指新的对象,但是 list1 与 list2 都是指向保存的同一个列表的引用,所以引用地址不会变。

list1 = [1,2,3]
list2 = list1
print(list1,id(list1))
print(list2,id(list2))
list1.append(4)
print(list1,id(list1))
print(list2,id(list2))

# 执行结果
[1, 2, 3] 1196611494536
[1, 2, 3] 1196611494536
[1, 2, 3, 4] 1196611494536
[1, 2, 3, 4] 1196611494536

浅拷贝
不可变对象的拷贝
不可变对象只在修改的时候才会在内存中开辟新的空间,而拷贝实际上是让多个对象同时指向一个引用,和对象的赋值没有区别,可以理解为不可变对象的拷贝就是对象赋值。

import copy
a = 1
b = copy.copy(a)
print("变量a的id :", id(a))
print("变量b的id :", id(b))

# 执行结果
变量a的id1576763504
变量b的id1576763504

可变对象的拷贝
可变对象的拷贝会在内存中开辟一个新的空间来保存拷贝的数据,当改变之前的对象时,对拷贝后的对象没有任何影响。

import copy
list1 = [1, 2, 3, 4]
list2 = copy.copy(list1)
print("变量list1的id :", id(list1))
print("变量list2的id :", id(list2))
# 执行结果
变量list1的id3092259686216
变量list2的id3092259686408

list1[0] = "A"
print("变量list1的id :", id(list1))
print("变量list2的id :", id(list2))
# 执行结果
变量list1的id3092259686216
变量list2的id3092259686408

猜你喜欢

转载自blog.csdn.net/lipandeng_acb/article/details/87968142