(1)任何一个对象a均有一个唯一的id识别号,用内置函数id(a)来获得该号。在Cpython中,id(a)表示对象a在内存中的地址。
id(object) -> integer
Return the identity of an object. This is guaranteed to be unique among
simultaneously existing objects. (Hint: it's the object's memory address.)
可以用"is"语句判断两个对象的识别号是否一致,例如 a is b,而a == b是比较两者的值。
(2)Python中的变量可分为可变类型和不可变类型。
不可变类型包括:数字、字符串、元组、布尔
可变类型包括:列表、字典、集合
不可变类型表示不允许变量的值发生变化,如果改变了变量的值,相当于是新建了一个对象。可变类型表示该类型的变量可以原地修改。
判断变量的类型是可变类型还是不可变类型,可以通过修改该变量前后id值是否发生变化来判断,如id发生变化,则为不可变类型,反之为可变类型。(注:元组不支持该操作,因为元组默认不可变)。
a = 3
print(id(a))
a = 4
print(id(a))
结果:
505986616
505986632
说明数字是不可变的,看似能修改变量a的值,其实a=4时, a的内存地址已变化。
b = 'hello'
print(id(b))
b = 'hello world'
print(id(b))
结果:
226397440
323543992
同样,字符串变量b看似能修改值,其实是在内存中新的地址创建了新的对象。
c = [1,2,3]
print(id(c))
c.append(4)
print(id(c))
d = {'a':1,'b':2,'c':3}
print(id(d))
d.pop('c')
print(id(d))
e={1,2,3}
print(id(e))
e.add(4)
e.remove(1)
print(id(e))
以上三段代码运行发现,修改列表、字典、集合变量的值时,变量的id值不发生任何改变,说明这三种数据类型均为可变类型。
(3)可变类型内部包含不可变类型的情况
a=['abc',1,2]
print(id(a),id(a[0]))
a[0] = 'efg'
print(id(a),id(a[0]))
运行结果:
322594056 12223552
322594056 325218816
说明修改可变类型变量列表内部的不可变对象字符串时,列表的id不发生变化,但内部的不可变类型对象的字符串对象的id值发生了变化。
(4)小数据池
a = 3
b = 3
print(id(a) == id(b))
运行结果:True
a = 300
b = 300
print(id(a) == id(b))
运行结果:False
Python自动将-5~256的整数进行了缓存,当你将这些整数赋值给变量时,并不会重新创建对象,而是使用已经创建好的缓存对象。
对于字符串变量,当字符串的长度>1,且只含有大小写字母,数字,下划线时,才会默认驻留。当字符串变量的长度为0或者1,使用小数据池。
a = 'hello_2020'
b = 'hello_2020'
print(id(a) == id(b))
a = 'hello world'
b = 'hello world'
print(id(a) == id(b))
运行结果:
True
False
对于bool变量同样适用小数据池。
a = True
b = True
print(id(a) == id(b))
运行结果:
True
以上情况外,均不使用小数据池,例如:
a = [1,2,3,4]
b = [1,2,3,4]
print(id(a) == id(b))
运行结果:
False
(5)知识检验
例1:
a = 'abc'
a.capitalize()
print(a)
运行结果是 abc,为什么不是Abc?
例2:
a =[100,200,300]
a = a.append(400)
print(a)
运行结果:None,为什么不是[100, 200, 300, 400]