从上面的文章可以总结出Python中变量名和对象是分离的,通过“=”给变量赋值时,实际上引用变量指向一个对象,而这个对象则是对应内存中存储的一块数据,取消引用时,Python会回收内存。
In [1]: a=100
这个语句执行的意思是:设置内存中一块区域存储对象“100”,引用变量a指向这个对象。
可以查询该对象的内存地址
In [3]: id(a)
Out[3]: 9095328
再执行语句b=a,又是如何实现呢?
In [2]: b=a
In [6]: id(b)
Out[6]: 9095328
b=a 执行结果是,变量b指向a所指向的对象,这个与c语音中复制内存值的机制不一样。
再思考下一旦赋值后,能不能改变呢?
In [7]: a=100
In [8]: id(a)
Out[8]: 9095328
In [9]: a=200
In [33]: id(a)
Out[33]: 139731596731920
答案是no,从上图可知重新赋值后,实际是指向了另外一个对象,id结果并不一样。
这种数据类型就是不可变类型
我们再来看看b的引用对象有没有发生变化?
In [34]: id(b)
Out[34]: 9095328
可以看出b还是指向以前的对象。这个地方与可变类型不一样。
再来看看可变的,例如:
In [35]: m=[10,20,"abc"]
In [36]: id(m)
Out[36]: 139731610235208
In [37]: m.append(30)
In [38]: id(m)
Out[38]: 139731610235208
In [39]: m.pop()
Out[39]: 30
In [40]: m
Out[40]: [10, 20, 'abc']
In [41]: id(m)
Out[41]: 139731610235208
可以看出变量m数据修改时,指向的对象一直没有发生变化。
同样的 n=m,m发生变化时,n会变化吗?
In [40]: m
Out[40]: [10, 20, 'abc']
In [41]: id(m)
Out[41]: 139731610235208
In [42]: n=m
In [45]: id(n)
Out[45]: 139731610235208
In [46]: m.insert(1,50)
In [47]: m
Out[47]: [10, 50, 20, 'abc']
In [48]: id(m)
Out[48]: 139731610235208
In [49]: id(n)
Out[49]: 139731610235208
In [50]: n
Out[50]: [10, 50, 20, 'abc']
n的值会随着m一起发生变化,且指向同一对象。
因此
不可变类型就是指向的对象内容不允许发生改变,只能改变引用指向。
包括:字符串、数字、元组
可变类型就是指向的对象内容允许发生改变,可以改变对象内容而引用不变。
包括:列表、字典
注意
1、字典中的key值只能是不可变内容
2、对于不可变类型的全局变量来说,因其指向的对象不能修改,所以不使用global时无法修改全局变量。
3、对于可变类型的全局变量来说,因其指向的对象可以修改,所以不使用global时也可修改全局变量。
4、Python中函数参数是引用传递(注意不是值传递)。对于不可变类型,因变量不能修改,所以运算不会影响到变量自身;而对于可变类型来说,函数体中的运算有可能会更改传入的参数变量。