python中的数据类型
0. 引子
工作中涉及到python,也有一段时间了,发现个很容易忽略的问题,居然一直没注意到。
dict = {}
def func(dict):
dict['key'] = 'value'
func(dict)
print dict
以前印象里,python这里的dict结果应该是空的,理所当然的认为了,函数中拿到的dict是另一个被复制了的dict。
可是这里打印的结果是:
{'key': 'value'}
这几天任务比较少,就花时间研究了一下,顺便把学习的过程记录在这
1. python中变量
python中的变量拿到的都是引用,python中的变量赋值操作,实际上是把实际内存中存储数据的引用交给了变量。
1 a = 1 # 创建了一个数字的内存区域,并把这块内存的引用交给了a 2 b = 1 # 常量1在内存中存在,并不重复创建,把引用交给b 3 c = a # 把a的引用交给c 4 5 id(a) 7 id(b) 9 id(c)
结果
7145672
7145672
7145672
下边做另一个试验,如果有两个变量指向同一块内存,我修改了其中一个会发生神马?这里奇怪的事情发生了
1 a = 1 2 b = a 3 4 id(a) # 7145672 5 id(b) #7145672 6 7 b += 1 8 9 id(a) #7145672 10 id(b) #7145648
这里看到,如果修改了变量b的值,从结果上来看,a和b指向了不同的内存区域,那么可以这样理解,python解释器发现,对b进行了修改,那么,需要为b创建一个新的内存区域。 但是,这个这么解释是完全准确的吗? 再看下边这段代码
1 a = [1,2] 2 b = a 3 4 id(a) #182895318800 5 id(b) #182895318800 6 7 a.append(3) 8 9 id(a)#182895318800
10 id(b) #182895318800
在这里,我做了和上边相同的操作,但是a,b却依旧指向相同的内存块。
同样是做修改,为什么结果不同呢?
两段代码的区别主要是,一个是int类型,一个是list类型。 python中,数据类型可以分为两类:可变类型&不可变类型,其中可变类型包括list, dict,不可变类型包括int,float, string, tuple.
可变指的是,内存中实际存储的数据是可以修改的,而不可变则相反。
在int的代码段中,因为int是不可变类型,在修改b的时候,解释器是不能把a,b公用的数据修改的,只能取出a的值,计算出一个新的值,然后申请一块新的内存存放新的数字,并把引用交给b
另外,python为了节省小整数的申请内存的开销,会为小整数留出一块空间做缓存,这里小整数的范围是【-5,256】,所以下边这段代码的结果是
1 a = 257 2 b = 257 3 4 id(a) #7833072 5 id(b) #8035752 6 7 a = 256 8 b = 256 9 id(a) #7151504 10 id(b) #7151504
2. python中的赋值,拷贝及深拷贝
说起拷贝,就要说一下copy模块和copy模块中的copy方法和deepcopy方法,看代码
1 import copy 2 a = [1,2,3,[1,2]] 3 b = a 4 c = copy.copy(a) 5 d = copy.deepcopy(a) 6 7 id(a) #182895320384 8 id(b) #182895320384 9 id(c) #182895353936 10 id(d) #182895320744 11 12 id(b[3]) #182895318800 13 id(c[3]) #182895318800 14 id(d[3]) #182895320456
python中的赋值实际上是引用的赋值。
这段代码中的浅拷贝,确实为c申请了一块新的内存区域,但是list中的嵌套的list却不是新申请的新内存
不同的是,深拷贝,不仅为c申请了一块新的内存区域,也为list中嵌套的子list申请了一块新的内存【递归拷贝】