龙空技术网

CPython源码阅读13-bytes对象合并底层原理

篮球鉴赏家小华 83

前言:

而今同学们对“byte合并”大概比较关注,姐妹们都需要剖析一些“byte合并”的相关文章。那么小编也在网摘上搜集了一些对于“byte合并””的相关资讯,希望兄弟们能喜欢,咱们快快来学习一下吧!

当我们在键盘上敲下如下代码时,它的底层是如何实现的。第一行对bytes1这个bytes对象赋值,第二行对bytes2这个bytes对象赋值,第三行两个bytes对象相加。从结果来看,把两个bytes对象合并在一起了,使用这个“+”符号,通过多态实现了bytes对象合并(concat)这一功能。

两个bytes对象的concat

通过这个图示,理解一下源码

源码图示

//cpython-master\Objects\bytesobject.cstatic PyObject *bytes_concat(PyObject *a, PyObject *b){    Py_buffer va, vb; //两个表示缓冲区的局部变量    PyObject *result = NULL;//用于保存结果    va.len = -1;    vb.len = -1;//初始值为-1,表示此时缓冲区为空     //将a、b中的ob_sval拷贝到缓冲区中,返回非0,则拷贝成功    if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 ||        PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) {      //用于检查两个合并的对象是否都为bytes对象        PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",                     Py_TYPE(b)->tp_name, Py_TYPE(a)->tp_name);        goto done;//释放缓冲区,防止内存泄露    }   //a与b中是否有一个长度为0,如果是,直接将其中一个赋值给result    if (va.len == 0 && PyBytes_CheckExact(b)) {        result = b;        Py_INCREF(result);//增加result的引用计数        goto done;//释放缓冲区,防止内存泄露    }    if (vb.len == 0 && PyBytes_CheckExact(a)) {        result = a;        Py_INCREF(result);        goto done;    }   //判断两个字节序列合并之后,是否超过最大限制    if (va.len > PY_SSIZE_T_MAX - vb.len) {        PyErr_NoMemory();        goto done;    }   //为result分配内存,大小为 va.len + vb.len    result = PyBytes_FromStringAndSize(NULL, va.len + vb.len);    if (result != NULL) {      //将va缓冲区中的buf内容拷贝到result的ob_sval中。拷贝长度为 va.len        memcpy(PyBytes_AS_STRING(result), va.buf, va.len);      //将vb缓冲区中的buf内容拷贝到result的ob_sval中。拷贝长度为 vb.len。从 va.len的位置开始拷贝        memcpy(PyBytes_AS_STRING(result) + va.len, vb.buf, vb.len);    }  done:    if (va.len != -1)        PyBuffer_Release(&va);    if (vb.len != -1)        PyBuffer_Release(&vb);    return result;}

标签: #byte合并