本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名原文链接~~~

Python基础(7)之数据在内存中的缓存机制和小数据池

微信搜索 zze_coding 或扫描 👉 二维码关注我的微信公众号获取更多资源推送:


测试环境:Mac OS + Python3.7.4。

在同一文件里

在同一文件中针对各基本类型的变量做如下测试:

# 在同一文件中
# 测试环境:MacOS Python3.7.4
# 1、对于整型而言,有相同值的两个变量在内存中的 id 值一致。
a = -12342143124
b = -12342143124
print(id(a) == id(b))  # True

a = 234324324234
b = 234324324234
print(id(a) == id(b))  # True

# 2、对于浮点数而言,有相同值的两个变量在内存中的 id 值一致。
a = -12313131313.213133213
b = -12313131313.213133213
print(id(a) == id(b))  # True

a = 342442342342.4324234
b = 342442342342.4324234
print(id(a) == id(b))  # True

# 3、对于布尔值而言,有相同值的两个变量在内存中的 id 值一致。
a = True
b = True
print(id(a) == id(b))  # True

a = False
b = False
print(id(a) == id(b))  # True

# 4、对于虚数而言,有相同值的两个变量在内存中的 id 值一致。
a = 1213213213123j
b = 1213213213123j
print(id(a) == id(b))  # True

a = -123213213213123j
b = -123213213213123j
print(id(a) == id(b))  # True

# 5、对于复数而言,有相同值的两个变量在内存中的 id 值一致。
a = 213213231312 + 324324234j
b = 213213231312 + 324324234j
print(id(a) == id(b))  # True
a = -21321321321 - 3244324234j
b = -21321321321 - 3244324234j
print(id(a) == id(b))  # True

# 6、对于字符串而言,有相同值的两个变量在内存中的 id 值一致。
a = 'abcd$234234@342^^&'
b = 'abcd$234234@342^^&'
print(id(a) == id(b))  # True

# 7、对于元组而言,有相同值的两个变量在内存中的 id 值一致。
a = tuple()
b = tuple()
print(id(a) == id(b))  # True

a = (12312312421, 123123, 4324, 'deawda', '@#$@$%@')
b = (12312312421, 123123, 4324, 'deawda', '@#$@$%@')
print(id(a) == id(b))  # True

# 8、对于列表而言,有相同值的两个变量在内存中的 id 值不一致。
a = []
b = []
print(id(a) == id(b))  # False

a = [1, 2, 3]
b = [1, 2, 3]
print(id(a) == id(b))  # False

# 9、对于集合而言,有相同值的两个变量在内存中的 id 值不一致。
a = set()
b = set()
print(id(a) == id(b))  # False

a = {1, 2, 3}
b = {1, 2, 3}
print(id(a) == id(b))  # False

# 10、对于字典而言,有相同值的两个变量在内存中的 id 值不一致。
a = {}
b = {}
print(id(a) == id(b)) # False

a = {'zs':12,'ls':20}
b = {'zs':12,'ls':20}
print(id(a) == id(b))  # False

小结一下,在同一文件中并且值相同的两个变量:

  • 如果它们是 Number 类型(int、float、bool、complex) 、字符串类型或元组类型时,它们的值在内存中的地址肯定相同;
  • 如果它们是列表、集合或字典类型,它们的值在内存中的地址肯定不同;

在不同文件里

数字类型测试

>>> a = -6
>>> b = -6
>>> id(a) == id(b)
False
>>> a = -5
>>> b = -5
>>> id(a) == id(b)
True
>>> a = 256
>>> b = 256
>>> id(a) == id(b)
True
>>> a = 257
>>> b = 257
>>> id(a) == id(b)
False
>>> a = 1.2
>>> b = 1.2
>>> id(a) == id(b)
False
>>> a = True
>>> b = True
>>> id(a) == id(b)
True
>>> a = 1 + 2j
>>> b = 1 + 2j
>>> id(a) == id(b)
False

小结:

  • 两个文件中变量值类型为整型、值相同、且范围在 -5 ~ 256 时;
  • 两个文件中变量值类型为布尔、且值相同时;

它们就指向内存中的同一块地址。

字符串测试

>>> a = '#'
>>> b = '#'
>>> id(a) == id(b)
True
>>> a = 'a'
>>> b = 'a'
>>> id(a) == id(b)
True
>>> a='abcdawedea_123'
>>> b='abcdawedea_123'
>>> id(a) == id(b)
True
>>> a='abc#'
>>> b='abc#'
>>> id(a) == id(b)
False

小结:

  • 两个文件中变量值类型为字符串、值相同、且字符串长度等于 1;
  • 两个文件中变量值类型为字符串、值相同、字符串长度大于 1、且只含有大小写字母、数字、下划线时;

它们就指向内存中的同一块地址。

使用乘号得到的字符串

>>> a = 'abc#'
>>> b = a * 1
>>> c = a * 1
>>> id(b) == id(c)
True
>>> b = a * 2
>>> c = a * 2
>>> id(b) == id(c)
False
>>> a = 'abc'
>>> b = a * 2
>>> c = a * 2
>>> id(b) == id(c)
False

小结:用 * 号得到的字符串,当乘数等于 1 时,无论什么字符串 * 1,都默认指向内存中的同一块地址。

小结

对于整数而言:

  • Python 在内存中创建了 -5 ~ 256 范围的整数,提前驻留在了内存的一块区域,这个区域也叫做小数据池。如果是不同文件(模块)的两个变量声明了在 -5 ~ 256 之间的同一个值,那么这两个变量的 id 就一致,即这两个变量的值都同时指向一个值的地址,以达到节省空间的目的。

对于普通字符串而言:

  • 字符串的长度为 0 或者 1 时,默认驻留小数据池;
  • 字符串的长度大于 1,且只含有大小写字母,数字,下划线时,默认驻留小数据池;

对于用 * 复制的字符串而言:

  • * 号复制得到的字符串,只有当乘数等于 1 时,无论什么字符串 * 1,都会让这个字符串被缓存,后续有通过 * 1 复制相同字符串时,就默认使用这个缓存的字符串;

无论是变量缓存机制还是小数据池的驻留机制,都是为了节省内存空间,提升代码的执行效率。

指定驻留到小数据池

我们可以通过 sys 模块中的 intern 函数让指定的数据驻留到小数据池,例:

>>> from sys import intern
>>> a = 'abc#'
>>> b = 'abc#'
>>> id(b) == id(c)
>>> a = intern('abc#')
>>> b = intern('abc#')
>>> id(a) == id(b)
True

如果这篇文章对您有帮助,可点击下方链接分享给你的朋友们😋,如果遇到问题欢迎评论、留言~~~😇

评论

公众号:zze_coding

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×