CPython在github上的官方 repo: https://github.com/python/cpython
下面的总结都是给予我当前时间点(2019-05)看到的最新版本,3.8.0 alpha 4
首先在 python2 中,str类对应的 C struct 是 PyStringObject,但是在 python3 中该 strcut 改成了 PyBytesObject,但是 python3 中不再使用 PyBytesObject 作为 str 类的底层实现,这是因为 python2 中 str 默认是 bytes,转成 unicode 需要加 ‘u’ 前缀;而 python3 中默认是 unicode,转成 bytes 需要加 b 前缀。
#python2
s = "abc" # bytes
s = u"abc" # unicode
#python3
s = "abc" # unicode
s = b"abc" # bytes
PyBytesObject
PyBytesObject 定义在 include/bytesobject.h 文件:
#ifndef Py_LIMITED_API
typedef struct {
PyObject_VAR_HEAD
Py_hash_t ob_shash;
char ob_sval[1];
/* Invariants:
* ob_sval contains space for 'ob_size+1' elements.
* ob_sval[ob_size] == 0.
* ob_shash is the hash of the string or -1 if not computed yet.
*/
} PyBytesObject;
#endif
ob_shash 是 hash 值,可以计算一次后缓存起来,ob_sval 就是指向具体内存的指针。
PyObject_VAR_HEAD 定义在 Include/object.h 的一个 macro(宏),这个 macro 是用于标记大多数可变长对象的。(注意不是可变对象)
#define PyObject_VAR_HEAD PyVarObject ob_base;
typedef struct {
PyObject ob_base;
Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;
其中 ob_size 是元素个数,而 ob_base 是一个所有 python 对象的抽象 struct,定义如下:
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
ob_refcnt 是引用计数,ob_type 就是实际指向对象的指针。
至此整个结构体的脉络比较清晰,还是比较容易看懂的
具体的一些对 PyBytesObject 操作的函数是定义在 Objects/bytesobject.c 文件里的,这里抽取几个进行分析。
第一个是 PyBytes_FromString 函数,它是从一个 char* 中创建一个 PyBytesObject 对象
PyObject *
PyBytes_FromString(const char *str)
{
size_t size;
PyBytesObject *op;
assert(str != NULL);
size = strlen(str);
//检查传入的字符串长度是否过长
if (size > PY_SSIZE_T_MAX - PyBytesObject_SIZE) {
PyErr_SetString(PyExc_OverflowError,
"byte string is too long");
return NULL;
}
//如果长度为0, 则返回 nullstring
if (size == 0 && (op = nullstring) != NULL) {
#ifdef COUNT_ALLOCS
_Py_null_strings++;
#endif
Py_INCREF(op);
return (PyObject *)op;
}
//characters 是一个 单字符str缓冲池, 如果长度为1,就返回缓冲池地址
if (size == 1 && (op = characters[*str & UCHAR_MAX]) != NULL) {
#ifdef COUNT_ALLOCS
_Py_one_strings++;
#endif
Py_INCREF(op);
return (PyObject *)op;
}
/* Inline PyObject_NewVar */
// 分配长度为 PyBytesObject_SIZE+size 的内存空间, 注意此时 op.ob_sval 指向的是一个长度为 size+1 的内存空间
op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + size);
if (op == NULL)
return PyErr_NoMemory();
(void)PyObject_INIT_VAR(op, &PyBytes_Type, size);
op->ob_shash = -1;
// 将传入的 str 值拷贝到 op 结构体中
memcpy(op->ob_sval, str, size+1);
/* share short strings */
if (size == 0) {
nullstring = op;
Py_INCREF(op);
} else if (size == 1) {
characters[*str & UCHAR_MAX] = op;
Py_INCREF(op);
}
return (PyObject *) op;
}