目录
1、变量、对象和引用
2、对象的垃圾收集
3、共享引用(共享对象)
4、共享引用和相等
5、共享引用和在原位置修改
6、使用Python复制而不是创建引用可以避免原位置修改问题
7、浅拷贝和深拷贝
浅拷贝
深拷贝
1、变量、对象和引用
类型属于对象,而不是变量:变量名没有类型,对象才有类型,变量实质上是指向对象所在内存空间的指针,变量只是对对象的引用。 不同赋值,因为变量没有类型,所以实质上只是修改变量a为对不同类型的变量的引用。变量总是一个指向对象的指针,而不是可改变的内存区域的标签。给一个变量赋新值,并不是替换原始的对象,而是让这个变量去引用别的对象。通俗的讲就是一个变量被赋新值,只会影响这个变量,而不会影响其共享对象的变量。
a = 3
print(a)
# 输出为3
2、对象的垃圾收集
对象包括两个头部信息:类型标志位和引用计数器。 类型标志位指对象的类型,如int,str
引用计数器指当前引用该对象的数目,当数目为0时,对象的空间被自动回收。
a = 'hello python'
print(a)
a = 3 # --> 'hello python'被回收
print(a)
3、共享引用(共享对象)
两个变量同时引用同一对象
a = 'hello word'
b = a
print(a)
print(b)
4、共享引用和相等
== 比较两个被引用的对象是否具有相同的值 is 比较实现引用的指针是否相同,即是否引用同一对象,是否为共享引用。
a = [1, 2]
b = a
print(a == b)
print(a is b)
c = [1, 2]
d = [1, 2]
print(c is d)
print(c == d)
5、共享引用和在原位置修改
引用了一个在原位置上发生改变的对象,共享引用也同样改变。
list1 = [1, 2, 3, 4]
list2 = list1
print(list1)
print(list2)
list1 = "hello python" # 如直接给list1赋新值,则list2不变
print(list1)
print(list2)
如改变list2
所引用对象的一个元素,这类修改会在原位置上覆盖列表对象的某部分值。则list2
改变,尽管实质上并未改变list1
的值,list1
引用了一个在原位置上发生改变的对象,也同样改变。
list1 = [1, 2, 3, 4]
list2 = list1
print(list1)
print(list2)
# list1 = "hello python"
# print(list1)
# print(list2)
list2[2] = 100
print(list1)
print(list2)
6、使用Python复制而不是创建引用可以避免原位置修改问题
-
列表切片
# 列表切片
list1 = [1, 2, 3, 4]
list2 = list1[:]
print(list1)
print(list2)
list2[2] = 100
print(list1)
print(list2)
7、浅拷贝和深拷贝
浅拷贝
-
浅拷贝:copy函数可用于复制列表或字典等可变值,复制后的列表和原列表是两个独立的列表。
import copy list1 = [1,2,3] new_list = copy.copy(list1) new_list[0] = 0 print("old = ",list1) print("new = ",new_list)
深拷贝
-
深拷贝:如果要复制的列表中有列表,则使用
deepcopy()
函数完全复制。import copy list1 =[[1,2,3],['a','b','c']] new_list = copy.deepcopy(list1) #使用深copy. new_list[0][0] = 0 # 如果不使用deepcopy修改值不成功。 print("old = ",list1) print("new = ",new_list)