受碎片知识的影响,多数pthon新人对于数据类型的理解只停留在表层,缺乏全面认知。
不少小白也学老鸟人云亦云, 诸如 “ python简单,1天就能上手、3天就能速成、7天就能精通 ”。
只想快速搭框架、上爬虫、学Django、做数据分析.......
然而,不要忘了:
如果基础不牢、
水平肯定不高!!!
1、概述:
Python中的可变数据类型和不可变数据类型的分类依据是:
(保存数据的)源内存空间的数据是否允许修改。
不可变数据类型,指的是数据值不可改变的数据类型;
可变数据类型,指的是数据值可以改变的数据类型。
PS:学习资料讲究个 “起、承、折、转,深入浅出”,
楼上IT名词是不是没有温度、很生硬?下文是亲民的表述:
2、先导知识
为了节约内存、提升性能,程序语言对 内存空间、缓存进行了特殊设置。
2.1)内存空间
同一代码块下(一个文件中或1条交互式命令中),只有int、bool、str的id相同。
譬如,将值相同的int类型数据赋值给变量时,不会重新开辟新的内存空间。
而其它数据类型(如list)则要重新开辟内存空间。
2.2)缓存
同一代码块下,用同一缓存;
不同代码块下,适用另一套缓存机制(小数据池)。
【小数据池涉及 深copy、㳀copy,是另一个生僻的知识点,稍后再撰文详述】
3.不可变数据类型 *
1)源内存空间中数据不允许修改。
如果想要修改,只能开辟新内存空间,让变量引用指向新内存空间数据的地址。
2)不可变数据类型(可hash):int、float、str、bool、tuple。
【
hash是一种经典的数据加密算法,本身很烧脑、催眠。
高数扎实的盆友可以试试,万一能出专利、财富自由呢???萌新不要入深坑。
可以这样记忆:
hash 等价于“加密”,====> 约等于 不可变数据类型;
不hash/非hash 等价于“不加密”,====> 约等于 不可变数据类型;
】
简而言之,只要内存空间中的 int、float、str、bool、tuple 存在相同的数值,
再声明新的变量则不会开辟新空间,复用之前变量的空间。
生活中也有类似的例子
积极 -> 例子1——共用调料:
大家庭里,只要有了某调料(酱油、醋、糖、盐),就不再额外购买、直接共用了。
这种情况就共赢,格外方便、提高了效率。
消极 - >例子2——单位分房:
单位给员工提供免费住房,总有个别员工处心积虑地盯着别人正在住的房子,可能得到了小道消息这房子很特殊(比如,有免费温泉水、将来配车位、电梯不容易坏),总之,觉得别人分的房子格外好。铁了心不等单位分房,即使领导多次承诺的条件再优秀也不等分房(朝向、户型、家具),想方设法地把人家员工赶出来、抢这套已经分配出去的房子.......
这种情况就要警惕,恐怕会妨碍正常秩序、降低效率。
3.1)同值id相同
#%%% 同值str的 id 相同
str1 = "hello"
str2 = "hello"
print(id(str1)) # 140563160982672
print(id(str2)) # 140563160982672
#%%% 同值元组的 id 相同
tup1 = ('hello')
tup2 = ('hello')
print(id(tup1)) # 2836681197104
print(id(tup2)) # 2836681197104
3.2)修改后,值不改变
#%%% str 修改后,值不变
str1 = "hello"
str2 = str1.replace("h", "H")
print(str1) # str1 数值不发生改变
print(str2)
3.3)后值修改不影响前值
#%%% str 后值修改不影响前值
str1 = "hello"
str2 = str1
str2 = str2.replace("h", "H")
print('str1的数值是:',str1) #str1数值不发生改变
print('str2的数值是:',str2)
输出结果如下:
list1的数值是: ['h', 'e', 'l', 'l', 'o']
list2的数值是: ['H', 'e', 'l', 'l', 'o']
3.4)前值修改不影响后值
#%%% str 前值修改不影响后值
str1 = "hello"
str2 = str1
str1 = str1.replace("h", "H")
print('str1的数值是:',str1)
print('str2的数值是:',str2) #str2数值不发生改变
输出结果如下:
str1的数值是: Hello
str2的数值是: hello
4.可变数据类型 *
1)源内存空间中的数据可以修改,
不需要开辟新内存空间,只要在源内存基础上修改数据。
2)可变数据类型(不可hash):list、set、dict
简而言之,list、set、dict 即使数值相同,再声明新的变量会开辟新空间,
不会复用之前同值变量的空间。
4.1)同值id不相同
#%%% 同值list 的 id不相同
list1 = [1, 2, 3]
list2 = [1, 2, 3]
print(id(list1)) # 140563158976640
print(id(list2)) # 140563157220224
#%%% 同值集合set 的 id不相同
set1 = {1, 2, 3}
set2 = {1, 2, 3}
print(id(set1)) # 2836687970240
print(id(set2)) # 2836687970464
4.2)修改后,值改变
#%%% list 修改后,值改变
list1 = [1, 2, 3]
list1[0] = 4
print(list1) # [4, 2, 3] #list数值发生了改变
4.3)后值修改影响前值
#%%% list 后值修改影响前值
list1 = ['h','e','l','l','o']
list2 = list1
list2[0] = 'H'
print('list1的数值是:',list1) #list1的数值也会跟着发生改变
print('list2的数值是:',list2)
输出结果如下:
list1的数值是: ['H', 'e', 'l', 'l', 'o']
list2的数值是: ['H', 'e', 'l', 'l', 'o']
4.4)前值修改影响后值
#%%% list 前值修改影响后值
list1 = ['h','e','l','l','o']
list2 = list1
list1[0] = 'H'
print('list1的数值是:',list1)
print('list2的数值是:',list2) #list2的数值也会跟着发生改变
输出结果如下:
list1的数值是: ['H', 'e', 'l', 'l', 'o']
list2的数值是: ['H', 'e', 'l', 'l', 'o']
5、扩展——dict字典中的数据类型
dict字典中的数据类型,多数人一直忽视,其实,也是有讲究的。
键 Key 必须是不可变数据类型;
一般为str 、 int (元组也可以作字典的键)
值 Value 可以为任意数据类型。
dic = {(1,):3,(2,):'马'}
print(dic) #{(1,): 3, (2,): '马'}