概述
每种语言都有自己的数据类型特点,在Python中常听到“一切皆对象,一切皆为对象的引用”。按照更新对象的方式,Python的数据类型可以分为可变类型与不可变类型。
不可变数据类型:数值、字符串、布尔值。不可变对象就是对象的地址和值都不可变。新创建的对象被关联到原来的变量名,旧对象被丢弃,垃圾回收器会在适当的时机回收这些对象。
可变数据类型:列表、字典、集合。所谓的可变指的是可变对象的值可变,但是地址是不可变的。
不可变类型
举个例子:
a = 1
b = 1
print(id(a)) # 140732900610880
print(id(b)) # 140732900610880
c = a
print(id(c)) # 140732900610880
解释如下:
- 当我们定义了一个变量a,并其赋值1时,会在内存中找到一个位置存放(140732900610880)。
- 当我们将1定义成另外的变量b和c时,会发现它在内存中的地址不会发生变化。
- 同时Python计数器中会记录该处的引用数量是3,当引用数量为0时,会进行垃圾回收。
接下来,再在代码中体验一下字符串、元组和布尔这些不可变类型。
# 字符串型
str1 = "hello"
str2 = "hello"
print(id(str1)) # 2432397108480
print(id(str2)) # 2432397108480
print("--------------")
# 元组
t1 = (1, 2)
t2 = (1, 2)
print(id(t1)) # 2432397134664
print(id(t2)) # 2432397134664
print("--------------")
# 布尔类型
bool1 = True
bool2 = True
print(id(bool1)) # 140732900088144
print(id(bool2)) # 140732900088144
对于字符串型的数据,如“hello”在内存中的地址在程序运行过程中始终不变,将“hello”定义成str1和str2时,会发现该地址不会改变。
可以同理分析元组和布尔类型。
可变类型
相比于不可变数据类型,可变类型是指创建对象后,内存地址会发生变化
举个例子:以列表数据类型为例
- 当我们创建了变量list1,会在内存中开辟一个空间存储值[1, 2, 3]
- 当我们将值[1, 2, 3]定义成另一个变量list2时,会重新开辟一个内存空间,并丢弃旧的。
- 同理:字典和集合也是类似的
list1 = [1, 2, 3]
list2 = [1, 2, 3]
print(id(list1)) # 2577029751368
print(id(list2)) # 2577029751432
print("----------------")
# 字典
dict1 = {"name": "xia", "age": 20}
dict2 = {"name": "xia", "age": 20}
print(id(dict1)) # 1499195800384
print(id(dict2)) # 1499195800456
print("--------------")
# 集合
set1 = {"hello", "world"}
set2 = {"hello", "world"}
print(id(set1)) # 1293625998920
print(id(set2)) # 1293627676264
总结
不可变与可变类型中的“变”说的是内存地址。
- (不可变)如字符串型“hello”在内存中的地址是不变的,不管它被赋值给多少变量。
- (可变)如列表类型的[1, 2, 3]在被赋值给变量list1时,地址是2577029751368,当被赋值给变量list2时,地址又是2577029751432,虽然这两个变量的值都是[1, 2, 3],但是实际的地址确实不同的。
参考资料:
https://mp.weixin.qq.com/s/e8N-s2w4gYQPKETVH62EAg