不可变类型
在前面两节的代码测试中,整数型变量重新赋值后,id会发生改变,即变量名指向了新的内存空间。这样的类型被称为不可变类型,整数类型、浮点数类型、布尔类型和字符串类型都属于不可变类型。
可变类型
l = [1, 2, 3, 4]
print(l, id(l))
l[1] = 200
print(l, id(l))
del l[3]
print(l, id(l))
d = {'name': 'Jim', 'age': 18, 'gender': 'male', 'Nationality': 'American'}
print(d, id(d))
d['age'] = 19
print(d, id(d))
del d['Nationality']
print(d, id(d))
运行结果为:
[1, 2, 3, 4] 2774665241416
[1, 200, 3, 4] 2774665241416
[1, 200, 3] 2774665241416
{'name': 'Jim', 'age': 18, 'gender': 'male', 'Nationality': 'American'} 2774662671384
{'name': 'Jim', 'age': 19, 'gender': 'male', 'Nationality': 'American'} 2774662671384
{'name': 'Jim', 'age': 19, 'gender': 'male'} 2774662671384
代码分析:虽然对列表l和字典d的元素进行了重新赋值和删除操作,但l和d的id值都保持不变,这一点和不可变类型不同,是由变量在内存中的存储方式决定的。
对于x = 1000,栈区的名字x直接与堆区的值1000进行绑定,id值是1000的内存地址;
对于l = [1, 2, 3, 4],栈区的名字l直接与堆区的一个内存地址表进行绑定,id值是这个内存地址表的内存地址;在这个内存地址表中,依次存放着1、2、3、4这4个整数值在堆区中的地址。所以当把l[1]的值改成200,内存地址表的地址没有变,只是内存地址表的内容(第2个内存地址,从2的内存地址变为200的内存地址)发生改变;执行del l[3],是将内存地址表的第4个位置解除了与整数4的绑定关系,内存地址表的地址依然没有变。
列表和字典都是容器类型,将它们比作酒瓶,里面的酒(值)变了,但酒瓶还在那里,还是能找到。