菜鸟笔记
提升您的技术认知

python可变类型和不可变类型的区别

一、python的数据类型

在Python中主要有两种数据类型, 一种是可变数据类型, 另一种是不可变数据类型

可变类型(mutable):列表,字典(key是不可变)
不可变类型(unmutable):数字,字符串,元组

这里的可变不可变,从对象内存地址方向来说,是指内存中的值(value)是否可以被改变。
python所声明的变量都以对象的形式存在,存在于机器的固定内存之中。

二、不可变类型

不可变类型(unmutable):数字,字符串,元组

不可变数据类型在第一次声明赋值声明的时候, 会在内存中开辟一块空间, 用来存放这个变量被赋的值, 存放这个值的内存空间就是内存中的一个地址, 而这个变量实际上存储的, 并不是被赋予的这个值, 而是存放这个值所在空间的内存地址, 通过这个地址, 变量就可以在内存中取出数据了。

a = "python"   #定义一个字符串
print(id(a))  #第一次的地址
print(a)      
a = a.upper()  # 改变a的值
print(id(a))  
print(a)

# 打印结果
1971600470512
python
1971601305984
PYTHON

所谓不可变就是说, 我们不能改变这个数据在内存中的值, 所以当我们改变这个变量的赋值时, 只是在内存中重新开辟了一块空间, 将这一条新的数据存放在这一个新的内存地址里, 而原来的那个变量就不在引用原数据的内存地址而转为引用新数据的内存地址了。

num1 = 1
num2 = 1
num3 = 1
print(id(num1))
print(id(num2))
print(id(num3))

# 打印结果
1353670880
1353670880
1353670880

对于不可变类型int,无论创建多少个不可变类型,只要值相同,都指向同个内存地址。
总结:
python中的不可变数据类型,不允许变量的值发生变化,如果改变了变量的值,相当于是新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象,内部会有一个引用计数来记录有多少个变量引用这个对象。

三、可变类型

可变类型(mutable):列表,字典(key是不可变)

当你第一次声明了一个可变数据类型的时候, 同样会在内存中开辟一个空间, 并且将你所赋的数据值放在这块内存中, 然后将这个变量指向数据所在的内存地址, 不同的是, 可变数据类型可以对内存中的数据进行修改, 并且不会导致变量引用地址的变化。

# 可变类型的话,以list为例。list在append之后,还是指向同个内存地址,因为list是可变类型,可以在原处修改。
list1 = [1, 2, 3]  # 定义一个列表
print(list1)
print(id(list1))

list1.append(4)
print(list1)
print(id(list1))

# 打印结果
[1, 2, 3]
1971601424072
[1, 2, 3, 4]
1971601424072

但是这种修改仅限于Python中的内置方法, 比如list.append(), list.remove(), dict.pop(), dict.clear()等, 如果要是进行重新赋值的操作的话, 一样会改变变量的地址指向。

list1 = [1, 2, 3]
list2 = [1, 2, 3]
list3 = [1, 2, 3]

print(id(list1))
print(id(list2))
print(id(list3))

# 打印结果
1610181656264
1610181656200
1610181656392

当存在多个值相同的不可变类型变量时,指向不同的内存地址。
总结:
可变数据类型,允许变量的值发生变化,即如果对变量进行append等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,不过对于相同的值的不同对象,在内存中则会存在不同的对象,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份,这里不存在引用计数,是实实在在的对象。