python的缓存机制
- 前言
- id()函数
- 实例测试
前言
因为在创建数据时需要为数据创建内存,在销毁数据时需要释放内存,为了提高效率,Python使用了缓存机制。
什么是缓存机制呢?就是Python将一些值预先存好,当定义一个变量,并给他赋值时,会先匹配这些缓存好的值,如果有匹配的话,就将变量指向对应的内存。
那Python是不是将所有的值都预先存好了呢?显然是不可能的。在Python解释器启动时从内存空间中开辟出一小部分将一些比较常用的值预先定义好。
那今天我们就来了解一下,都有哪些预先存好的值。
id()函数
在进入正题之前,我们先了解一下id()函数:
id() 函数返回对象的唯一标识符,标识符是一个整数。
对应的内存地址是hex(id)
print(id(11), id("string"))
实例测试
先试试一个较小的值:
a = 11
b = 11
print(a is b)
print(id(a), id(b))
a和b的id值都是相同的,很显然他们指向了同一个内存地址。
再试试一个较大的值
c = 500
d = 500
print(c is d)
print(id(c), id(d))
当值为500时,id值已然不同。
我们用一个循环来看看具体有哪些值:
for num1, num2 in zip(range(-10, 500), range(-10, 500)):
if id(num1) == id(num2):
print(num1, end="\t")
由上可知预定义的值为 [-5, 256]
但是我还是有疑问,会不会是range()函数在搞鬼呢?
for num3 in range(-10, 500):
if num3 == 11:
print(id(num3) == id(11))
上面的例子都是int
型的数据,那么bool
和str
类型的数据呢?
先试试bool
:
bool1 = True
bool2 = True
print(id(bool1), id(bool2))
bool
值的id也是一样的
接下来是str
:
str1 = "aaa"
str2 = "aaa"
print(id(str1), id(str2))
这里的id也是相同的,但是这个值是我随意写的,不可能说Python解释器启动的时候就将这些值定好了吧?唯一合理的解释就是,我定义了str1之后,再定义str2时,会去检索是否已经定义过,如果已经定义,那么就将str2指向其地址。
那么怎么确定 **[-5, 256]**是一开始就创建好的呢?
我们反复运行开头的哪行代码,发现不管运行几次,都是相同的结果,
print(id(11), id("string"))
但是,如果重启运行时,
再运行,就会发现id(11)
的值跟之前的是一样的,而id("string")
的值跟之前不一样了,再继续运行时,则不会再变了。
如果是List(列表)、Tuple(元组)、Dictionary(字典)等数据类型的值呢?
list1 = [2, 2, 257]
list2 = [2, 257, 257]
print("2: ", id(list1[0]), id(list1[1]), id(list2[0]))
print("257:", id(list2[1]), id(list2[2]), id(list1[2]))
print("\n")
tuple1 = (2, 2, 257)
tuple2 = (2, 257, 257)
print("2: ", id(tuple1[0]), id(tuple1[1]), id(tuple2[0]))
print("257:", id(tuple2[1]), id(tuple2[2]), id(tuple1[2]))
对于257,list1和list2的257id的值是不同的,而同在list2中的257的id的值却是相同的;tuple中也是同样的;
对于整数2,不管是list1,list2,还是tuple1, tuple2的id的值都是相同的。
dict1 = {"a1": 2,
"a2": 2,
"a3": 257,
2: "abc"
}
dict2 = {"a1": 257,
"a2": 257,
"a3": 2,
257: "abc"
}
print("2:", id(dict1["a1"]), id(dict1["a2"]), id(dict2["a3"]))
print("\nstr key:")
for i in dict1.keys():
print(id(i))
print("\n")
print("257:", id(dict2["a1"]), id(dict2["a2"]), id(dict1["a3"]))
print("\nstr key:")
for i in dict2.keys():
print(id(i))
print("\nabc: ", id(dict1[2]), id(dict2[257]))
对于整数2,在dict1和dict2中不管是作为键还是值,id都是相同的;
对于整数257, id(dict2[“a1”])和id(dict2[“a2”])的值相同,但与id(dict1[“a3”])不同;
对于字符串,在dict1和dict2中不管是作为键还是值,id都是相同的。
那要是在不同的作用域呢?
int1, int2 = 2, 257
str1 = "abcd"
def func():
int3, int4 = 2, 257
print("id(int1) == id(int3):", \
id(int1) == id(int3),\
"\nid(int2) == id(int4):",\
id(int2) == id(int4))
str2 = "abcd"
print("id(str1) == id(str2):", id(str1) == id(str2))
func()
由此可见,预先定义的值是全局的,字符串也是全局的
下面这个图从参考链接而来,但是小数部分却得出了不同的结果: