众所周知,Python3 将所有字符串字符作为 Unicode 代码点。
type('\x0d')
<class 'str'>
type(b'\x0d')
<class 'bytes'>
b'\x0d'
的ascii为13
,以0000 0111
的形式存储在内存中,'\x0d'
是否以与0000 0111
相同的格式存储?它们在内存中是否相等?#My python version
python3 --version
Python 3.9.2
#in python cli
len(b'\x0d')
1
import sys
print(sys.getsizeof(b'\x0d'))
34
b\x0d
在内存中不是以00000111
的形式存储的吗?
print(sys.getsizeof('\x0d'))
50
使用
sys.getsizeof
让我明白:
string
和bytes
在python3中以不同的对象存储。b\x0d
在内存中以00000111
的形式存储时,它是基于某种抽象层次,实际上b\x0d
对于cython3在pc的内存中是以34字节存储的?有兴趣的可以看看CPython中各个对象的内存内容。对象的大小可以通过
sys.getsizeof(obj)
查询,内存地址恰好是当前实现中对象的id(obj)
。 ctypes
模块有一个string_at
函数,它需要一个内存地址和大小来读取内存:
>>> import sys
>>> import ctypes
>>> x = '\x0d'
>>> ctypes.string_at(id(x), sys.getsizeof(x)).hex()
'02ca9a3b0000000070a427b3fb7f00000100000000000000c879dc5ef7a24b87e40000000000000000000000000000000d00'
>>> x = b'\x0d'
>>> ctypes.string_at(id(x), sys.getsizeof(x)).hex()
'01ca9a3b00000000b0b126b3fb7f00000100000000000000c879dc5ef7a24b870d00'
在上面你可以看到对象有不同的内存映像,但在这种情况下,至少,对象中的数据存储在最后一个字节
0d 00
并且由于 CPython 使用 latin-1
8 位编码而完全相同存储 Unicode 字符串(详见PEP 393)。 CPython 添加了一个空终止符作为另一个实现细节。其他字节表示 CPython 中 PyBytes
和 PyUnicode
对象实现中的数据。
CPython 目前使用每个字符最少 8、16、32 位(在 LATIN-1、UTF-16(?)、UTF-32 中)对(文本)字符串进行编码,以适应字符串中包含的所有字符。
所以,如果你所有的字符都符合 LATIN-1 编码——它与 unicode 代码点 1:1 匹配 <256, it will use only one byte per character internally.
我似乎在某个地方(抱歉,这是一个问题的评论辩论,但我现在找不到)有未来计划将文本字符串 utf-8 编码保存在内存中,以避免大量绝大多数与文本相关的工作流中的开销,其中 utf-8 字节字符串被解码为很少使用的内部表示。 Pypy 目前使用这种方法。