本文介绍的是两种节省内存的方案:
- 一个字符串的每个字符在占用空间大小是相同的,取决于字符串中最大的字符。
- 短字符串会放到一个全局的字典中,该字典中的字符串成了单例模式,从而会节省内存。
第一种方案 可变方式定长编码
从Python3起,字符串就采用了Unicode
编码(注意这里并不是utf8编码,尽管.py
文件默认编码是utf8
)。而每个标准的Unicode
字符占用4个字节,这对有些字符来说无疑是种浪费。
Unicode是一种字符集,ISO也是一种字符集。为了便于传输,衍生出utf8,utf16等编码方案来节省内存。
UCS2 和 UCS4 都是固定编码长度的方案
Python内部也采用类似于Unicode字符集的形式来节省内存,如果字符串中所有字符都在ascii
码范围内,那么就可以使用占用一个字节的latin-1
编码进行存储。而字符串中存在了需要占用两个字节(比如中文字符),那么整个字符串就采用占用两个字节的ucs-2
编码进行存储。假如字符串中存在emoji表情,那么将用占四个四个字节的ucs-4
编码进行存储。
- 每个字符占一个字节(Latin-1)
- 每个字符占两个字节(ucs-2)
- 每个字符占四个字节(ucs-4)
对于上述的结论可以使用以下代码进行计算验证(getsizeof不能获取准确的内存占用,只能通过计算得出结论):
import sys
sys.getsizeof(字符串)
image.png
那么还有一个问题:既然python文件默认用的是utf8编码,那为什么python内部不用utf8编码而用Unicode呢:
因为utf8不是固定长度的,它可以占一个字节,也可以占两个字节,也可以占三个字节。这就导致访问字符串中单个字符时非常麻烦(需要同时统计字符个数和占用字节长度),这样时间复杂度由原来的O(1)变成了O(n),所以python内部采用了定长的方式存储字符串。
第二种方案 小数据池
参考资料:
Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4.md
字符串在Python内部是如何省内存的
网友评论