一. 数据类型
- 变量:是一个系统表的元素,拥有指向对象的连接空间
- 对象:被分配的一块内存,存储其所代表的值
- 引用:是自动形成的从变量到对象的指针
- 类型:属于对象,而非变量
1. 不可变数据类型
一旦创建就不可修改的对象,包括数值类型、字符串、布尔类型、元组
#定义一个变量a
a = "python"
print(id(a))
b=10
print(id(b))#140710918126944
b="hello"
print(id(b))#1629196172080
2. 可变数据类型
可以修改的对象,包括列表、字典、集合
3. 赋值
只是复制了新对象的引用,不会开辟新的内存空间
a = 10
b = a
print(id(a))#140711658356064
print(id(b))#140711658356064
c = [1, 2, 3]
d = c
print(id(c))#1930836595208
print(id(d))#1930836595208
二. 深浅拷贝
拷贝就是复制操作,其拷贝的值是相同的,但引用关系有所不同
1. 浅拷贝
浅拷贝,能力有限,只能拷贝最外层对象(只需要为外层开辟内存空间),无法拷贝内层对象
① 简单的可变数据类型
对于简单的可变数据类型,浅拷贝相当于把原对象的值进行拷贝,需要在内存中开辟一块新的内存空间
import copy
list1 = [1, 3, 5]
list2 = copy.copy(list1)
# 值-相同
print(list1) # [1, 3, 5]
print(list2) # [1, 3, 5]
# 地址-不同
print(id(list1)) # 1541605108232
print(id(list2)) # 1541605108296
② 复杂的可变数据类型
对于复杂的可变数据类型,浅拷贝只能拷贝可变数据类型的最外层对象,而无法拷贝内层对象,所以只需要为最外层对象开辟内存空间,内层对象拷贝后的引用关系与原对象保持不变
import copy
list1 = [1, 3, 5,[7,9]]
list2 = copy.copy(list1)
# 值-相同
print(list1) # [1, 3, 5,[7,9]]
print(list2) # [1, 3, 5,[7,9]]
# 地址-不同
print(id(list1)) # 1541605108232
print(id(list2)) # 1541605108296
# 地址-相同
print(id(list1[3])) # 2850758572616
print(id(list2[3])) # 2850758572616
③ 简单的不可变数据类型
对于简单的不可变数据类型,不可变数据类型地址一旦固定,值就无法改变了,又由于浅拷贝需要把自身的对象空间赋值给另外一个变量,为了保证数据一致,只能让其指向相同的内存空间(不需要额外开辟内存空间)
import copy
a = (1, 3, 5)
b = copy.copy(a)
# 值-相同
print(a) # (1, 3, 5)
print(b) # (1, 3, 5)
# 地址-相同
print(id(a)) # 2350406710360
print(id(b)) # 2350406710360
④ 复杂的不可变数据类型
对于复杂的不可变数据类型,浅拷贝只能拷贝变量的值,无法拷贝内存空间(无法开辟新的内存空间),无法拷贝内层对象
import copy
a = (1, 3, 5, (7, 9))
b = copy.copy(a)
# 值-相同
print(a) # (1, 3, 5, (7, 9))
print(b) # (1, 3, 5, (7, 9))
# 地址-相同
print(id(a)) # 2350406710360
print(id(b)) # 2350406710360
# 地址-相同
print(id(a[3])) # 2109112683592
print(id(b[3])) # 2109112683592
无法拷贝内层对象
import copy
a = (1, 3, 5, (7, 9))
b = copy.copy(a)
# 值-相同
print(a) # (1, 3, 5, [7, 9]))
print(b) # (1, 3, 5, [7, 9])
# 地址-相同
print(id(a)) # 2350406710360
print(id(b)) # 2350406710360
# 地址-相同
print(id(a[3])) # 2109112683592
print(id(b[3])) # 2109112683592
⑤ 浅拷贝栗子
Ⅰ. 切片操作
lst = [1,2,[3,4]]
切片操作:lst1 = lst[:] 或者 lst1 = [each for each in lst]
[:]
它与[0:]
相似,意思是从0索引拆分到末尾。它返回一个新列表。
Ⅱ. 工厂函数
lst1 = list(lst)
Ⅲ. copy模块中的copy函数
lst1 = copy.copy(lst)
但是在lst中有一个嵌套的list[3,4],如果我们修改了它,情况就不一样了。
2. 深拷贝
深拷贝:和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。深拷贝出来的对象是一个全新的对象,不再与原来的对象有任何关联。
① 简单的可变数据类型
对于简单的可变数据类型,深拷贝可以对对象进行完全拷贝,生成一块独立的内存空间,两个变量没有任何关系
import copy
a = [1, 3, 5]
b = copy.deepcopy(a)
# 值-相同
print(a) # [1, 3, 5]
print(b) # [1, 3, 5]
# 地址-不相同
print(id(a)) # 1763734399496
print(id(b)) # 1763734399560
② 复杂的可变数据类型
对于复杂的可变数据类型,深拷贝可以对对象进行完全拷贝,不仅可以拷贝外层对象,也可以拷贝内层对象,而且完全独立
import copy
a = [1, 3, 5, [7, 9]]
b = copy.deepcopy(a)
# 值-相同
print(a) # [1, 3, 5, [7, 9]]
print(b) # [1, 3, 5, [7, 9]]
# 地址-不相同
print(id(a)) # 2891527236360
print(id(b)) # 2891527236616
# # 地址-不相同
print(id(a[3])) # 2891527236296
print(id(b[3])) # 2891527283912
③ 简单的不可变数据类型
对于简单的不可变数据类型,深拷贝也只能拷贝对象的引用关系,所以看到的记过就是a和b只想了相同的内存空间
import copy
a = (1, 3, 5)
b = copy.deepcopy(a)
# 值-相同
print(a) # (1, 3, 5)
print(b) # (1, 3, 5)
# 地址-相同
print(id(a)) # 1719625069656
print(id(b)) # 1719625069656
④ 复杂的不可变数据类型
对于复杂的不可变数据类型,深拷贝也只能拷贝对象的引用关系,所以看到的记过就是a和b只想了相同的内存空间
import copy
a = (1, 3, 5, (7, 9))
b = copy.deepcopy(a)
# 值-相同
print(a) # (1, 3, 5, (7, 9))
print(b) # (1, 3, 5, (7, 9))
# 地址-相同
print(id(a)) # 1928373693320
print(id(b)) # 1928373693320
# 地址-相同
print(id(a[3])) # 1928373701640
print(id(b[3])) # 1928373701640
3. 深浅拷贝特殊案例
① 可变嵌套不可变类型
外层是可变类型,多以可以进行完全拷贝(需生成内存空间),但内层对象是不可变数据类型,所以只能拷贝引用关系
import copy
a = [1, 3, 5, (7, 9)]
b = copy.copy(a)
c = copy.deepcopy(a)
# 值-相同
print(a) # [1, 3, 5, (7, 9)]
print(b) # [1, 3, 5, (7, 9)]
print(c) # [1, 3, 5, (7, 9)]
# 地址-不同
print(id(a)) # 2197686397896
print(id(b)) # 2197686397960
print(id(c)) # 2197686398216
# 地址-相同
print(id(a[3])) # 2197686094920
print(id(b[3])) # 2197686094920
print(id(c[3])) # 2197686094920
② 不可变嵌套可变类型
浅拷贝结论与之前结论一致,都只能拷贝引用关系
深拷贝,有点不同,如果这种类型使用深拷贝,其整体都可以进行完全拷贝
import copy
a = (1, 3, 5, [7, 9])
b = copy.copy(a)
c = copy.deepcopy(a)
# 值-相同
print(a)#(1, 3, 5, [7, 9])
print(b)#(1, 3, 5, [7, 9])
print(c)#(1, 3, 5, [7, 9])
#地址ab同,与c不同
print(id(a))#2983608461896
print(id(b))#2983608461896
print(id(c))#
#地址ab同,与c不同
print(id(a[3]))#2983608498888
print(id(b[3]))#2983608498888
print(id(c[3]))#2983608499144
浅拷贝
深拷贝