【通过Cpython3.9源码看看列表到底是咋回事】

news2024/11/18 5:58:39

在这里插入图片描述

列表结构

typedef struct {
    PyObject_VAR_HEAD
    /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
    PyObject **ob_item;

    /* ob_item contains space for 'allocated' elements.  The number
     * currently in use is ob_size.
     * Invariants:
     *     0 <= ob_size <= allocated
     *     len(list) == ob_size
     *     ob_item == NULL implies ob_size == allocated == 0
     * list.sort() temporarily sets allocated to -1 to detect mutations.
     *
     * Items must normally not be NULL, except during construction when
     * the list is not yet visible outside the function that builds it.
     */
    Py_ssize_t allocated;
} PyListObject;

其中定义了一个名为PyListObject的结构体。下面是这个结构体中的各个成员变量的详细解释:

  1. PyObject_VAR_HEAD:这是一个宏定义,它定义了一个PyObject对象的头部。在PyListObject结构体中,这个宏定义的作用是将PyListObject与PyObject对象关联起来,以便在Python解释器中进行类型检查和垃圾回收等操作。这个宏定义包含了以下内容:

    PyObject ob_base;
    Py_ssize_t ob_size;
    

    其中,PyObject是一个C语言结构体,表示Python对象的基础部分。ob_size是一个Py_ssize_t类型的整数,用于表示对象的大小。当使用PyObject_VAR_HEAD宏定义一个对象的头部时,ob_size会被设置为0这表示这个对象的大小是变长的,可以动态地分配内存。在Python中,许多对象,例如列表、元组、字典等,都是变长的,因此通常会使用PyObject_VAR_HEAD来定义这些对象的头部。这个宏定义的作用是将Python对象的头部和实际的数据结构关联起来,以便在Python解释器中进行类型检查和垃圾回收等操作。

  2. PyObject **ob_item:这是一个指针数组,用于存储Python列表中的元素。列表中的第一个元素存储在ob_item[0]中,以此类推。这个数组的大小由成员变量allocated决定。

  3. Py_ssize_t allocated:这是一个整型变量,表示ob_item数组中分配的内存空间大小。allocated的值必须大于等于列表中实际元素的个数ob_size。如果allocated的值为负数,则表示列表已被排序或已发生了变异,需要进行特殊处理。在Python的实现中,当对一个列表进行排序或者其他改变列表结构的操作时,为了避免出现潜在的问题,Python会对这个列表的allocated成员变量进行一个特殊的标记,将其值设置为负数,表示列表已经被排序或发生了变异。这个标记的作用是在随后的操作中,比如插入或删除元素时,检查这个列表是否已经被修改,如果是,则需要重新分配内存空间,并将allocated的值设置为正数。这个特殊处理的作用是保证了列表在被修改时的安全性,同时也保证了内存分配的效率。在Python中,列表的内存分配是动态的,如果不进行特殊处理,可能会出现内存分配过多或者过少的情况,导致程序效率降低。因此,为了保证Python程序的高效性和正确性,对于列表的修改操作,Python实现中会进行特殊处理,以确保内存的合理分配和程序的正确性。

  4. Invariants:这是一组不变式,用于描述列表ob_item和PyListObject结构体中的其他成员变量之间的关系。具体来说,这些不变式包括:

    • 0 <= ob_size <= allocated:ob_size表示列表中实际元素的个数,allocated表示ob_item数组的大小。这个不变式表明,ob_size必须小于等于allocated,并且ob_size和allocated必须都是非负数。
    • len(list) == ob_size:这个不变式表示列表的长度必须等于ob_size。
    • ob_item == NULL implies ob_size == allocated == 0:如果ob_item为NULL,则表示列表为空。此时,ob_size和allocated都必须为0。
    • list.sort() temporarily sets allocated to -1 to detect mutations.:当对列表进行排序操作时,allocated的值会被暂时设置为-1,以便检测列表是否发生了变异。
  5. Items must normally not be NULL, except during construction when the list is not yet visible outside the function that builds it.:在大多数情况下,列表中的元素不能为NULL。但是,在构建列表的函数中,如果列表还没有被返回并且在函数外部不可见,那么列表中的元素可以为NULL。

列表初始化

static int
list___init___impl(PyListObject *self, PyObject *iterable)
/*[clinic end generated code: output=0f3c21379d01de48 input=b3f3fe7206af8f6b]*/
{
    /* Verify list invariants established by PyType_GenericAlloc() */
    assert(0 <= Py_SIZE(self));
    assert(Py_SIZE(self) <= self->allocated || self->allocated == -1);
    assert(self->ob_item != NULL ||
           self->allocated == 0 || self->allocated == -1);

    /* Empty previous contents */
    if (self->ob_item != NULL) {
        (void)_list_clear(self);
    }
    if (iterable != NULL) {
        if (_PyObject_HasLen(iterable)) {
            Py_ssize_t iter_len = PyObject_Size(iterable);
            if (iter_len == -1) {
                if (!PyErr_ExceptionMatches(PyExc_TypeError)) {
                    return -1;
                }
                PyErr_Clear();
            }
            if (iter_len > 0 && self->ob_item == NULL
                && list_preallocate_exact(self, iter_len)) {
                return -1;
            }
        }
        PyObject *rv = list_extend(self, iterable);
        if (rv == NULL)
            return -1;
        Py_DECREF(rv);
    }
    return 0;
}

用于初始化Python列表对象。下面是这个函数的具体实现:

  1. 首先,函数会检查列表的一些不变量,确保它们满足要求。这些不变量包括:列表中元素数量的范围在0到allocated之间,allocated是已分配的内存数量,ob_item指向列表元素的指针数组。如果不变量不满足要求,函数会抛出一个assertion failure。
  2. 如果列表中已经有元素了,则调用_list_clear函数清空列表中的所有元素。
  3. 如果传入的iterable参数不为空,则根据iterable的长度预分配足够的内存空间。如果预分配的内存空间失败,则返回-1表示操作失败。
  4. 调用list_extend函数,将iterable中的所有元素添加到列表中。如果操作失败,则返回-1表示操作失败。
  5. 返回0表示操作成功。

总体来说,该函数的作用是初始化Python列表对象。它首先检查列表的一些不变量,确保它们满足要求。然后,它清空列表中的所有元素,并根据传入的iterable参数预分配足够的内存空间。最后,它调用list_extend函数,将iterable中的所有元素添加到列表中。

列表插入操作

int
PyList_Insert(PyObject *op, Py_ssize_t where, PyObject *newitem)
{
    if (!PyList_Check(op)) {
        PyErr_BadInternalCall();
        return -1;
    }
    return ins1((PyListObject *)op, where, newitem);
}
  1. 首先检查op是否为Python列表类型。如果op不是Python列表类型,则会抛出一个PyErr_BadInternalCall异常,并返回-1表示操作失败。
  2. 调用ins1函数,在指定位置where处将newitem插入到列表op中。
  3. 返回ins1函数的返回值,表示操作是否成功。
static int
ins1(PyListObject *self, Py_ssize_t where, PyObject *v)
{
    Py_ssize_t i, n = Py_SIZE(self);
    PyObject **items;
    if (v == NULL) {
        PyErr_BadInternalCall();
        return -1;
    }
    if (n == PY_SSIZE_T_MAX) {
        PyErr_SetString(PyExc_OverflowError,
            "cannot add more objects to list");
        return -1;
    }

    if (list_resize(self, n+1) < 0)
        return -1;

    if (where < 0) {
        where += n;
        if (where < 0)
            where = 0;
    }
    if (where > n)
        where = n;
    items = self->ob_item;
    for (i = n; --i >= where; )
        items[i+1] = items[i];
    Py_INCREF(v);
    items[where] = v;
    return 0;
}
  1. 首先获取列表的当前长度n,然后检查要插入的元素v是否为NULL。如果v为NULL,则表示出现了内部调用错误,会抛出一个PyErr_BadInternalCall异常,并返回-1表示操作失败。
  2. 如果列表已经达到了最大长度,那么插入操作无法进行,会抛出一个PyExc_OverflowError异常,并返回-1表示操作失败。
  3. 调用list_resize函数扩展列表的大小,使其能够容纳一个新的元素。如果扩展失败,会返回-1表示操作失败。
  4. 根据插入位置where的值,更新其值。如果where小于0,则表示从列表末尾开始往前数,因此需要计算出正确的位置。如果where大于n,则表示要在列表末尾插入元素,因此需要将where的值设置为n。
  5. 定义一个名为items的指针数组,用于存储列表中的元素。
  6. 使用for循环,将从where位置开始的所有元素往后移动一个位置,以腾出一个位置用于插入新元素。
  7. 使用Py_INCREF宏对新元素进行引用计数,然后将其插入到列表的where位置。
  8. 返回0表示插入操作成功。

总体来说,这个函数的作用是在Python列表中插入一个新元素。它首先检查输入参数是否正确,然后通过调用list_resize函数扩展列表的大小,并将所有元素往后移动一个位置,以腾出一个位置用于插入新元素。最后,使用Py_INCREF宏对新元素进行引用计数,并将其插入到指定位置。

列表删除操作

static PyObject *
list_remove(PyListObject *self, PyObject *value)
/*[clinic end generated code: output=f087e1951a5e30d1 input=2dc2ba5bb2fb1f82]*/
{
    Py_ssize_t i;

    for (i = 0; i < Py_SIZE(self); i++) {
        PyObject *obj = self->ob_item[i];
        Py_INCREF(obj);
        int cmp = PyObject_RichCompareBool(obj, value, Py_EQ);
        Py_DECREF(obj);
        if (cmp > 0) {
            if (list_ass_slice(self, i, i+1,
                               (PyObject *)NULL) == 0)
                Py_RETURN_NONE;
            return NULL;
        }
        else if (cmp < 0)
            return NULL;
    }
    PyErr_SetString(PyExc_ValueError, "list.remove(x): x not in list");
    return NULL;
}

这是一个名为list_remove的函数,用于从Python列表中移除指定的元素。下面是这个函数的具体实现:

  1. 定义一个名为i的Py_ssize_t类型变量,用于遍历列表中的所有元素。
  2. 使用for循环遍历列表中的所有元素。在每次循环中,从列表中获取一个元素obj,并使用PyObject_RichCompareBool函数将这个元素与待移除元素value进行比较。
  3. 如果比较的结果为1,则表示找到了待移除元素。此时,调用list_ass_slice函数,将列表中从i到i+1的元素删除,并返回Py_RETURN_NONE表示移除操作成功。
  4. 如果比较的结果为-1,则表示出现了异常。此时,直接返回NULL表示操作失败。
  5. 如果比较的结果为0,则继续遍历下一个元素。
  6. 如果在整个循环中都没有找到待移除元素,则会抛出一个PyExc_ValueError异常,并返回NULL表示操作失败。

总体来说,list_remove函数的作用是从Python列表中移除指定的元素。它遍历列表中的所有元素,将每个元素与待移除元素进行比较,找到待移除元素后调用list_ass_slice函数将其从列表中删除。如果整个列表中都没有待移除元素,则会抛出一个异常表示操作失败。

列表修改

#define PyList_SET_ITEM(op, i, v) (_PyList_CAST(op)->ob_item[i] = (v))

在 CPython 中,#define PyList_SET_ITEM(op, i, v) (_PyList_CAST(op)->ob_item[i] = (v)) 是一个宏定义,用于修改 Python 列表对象中指定索引位置的元素。

这个宏定义中包含了三个参数:

  1. op:要修改的 Python 列表对象。
  2. i:要修改的元素的索引位置。
  3. v:新的元素值。

在宏定义中,使用了 _PyList_CAST 函数将 op 转换成了 PyListObject* 类型,从而可以使用 ob_item 成员来访问列表对象的元素。具体实现中,宏定义将指定索引位置 i 处的元素值设置为新的元素值 v,实现了 Python 列表对象中指定元素的修改。

列表查找

#define PyList_GET_ITEM(op, i) (_PyList_CAST(op)->ob_item[i])

在 CPython 中,#define PyList_GET_ITEM(op, i) (_PyList_CAST(op)->ob_item[i]) 是一个宏定义,用于获取 Python 列表对象中指定索引位置的元素。

这个宏定义中包含了两个参数:

  1. op:要访问的 Python 列表对象。
  2. i:要访问的元素的索引位置。

在宏定义中,使用了 _PyList_CAST 函数将 op 转换成了 PyListObject* 类型,从而可以使用 ob_item 成员来访问列表对象的元素。具体实现中,宏定义返回了指定索引位置 i 处的元素值,实现了 Python 列表对象中指定元素的访问。

列表比较

static PyObject *
list_richcompare(PyObject *v, PyObject *w, int op)
{
    PyListObject *vl, *wl;
    Py_ssize_t i;

    if (!PyList_Check(v) || !PyList_Check(w))
        Py_RETURN_NOTIMPLEMENTED;

    vl = (PyListObject *)v;
    wl = (PyListObject *)w;

    if (Py_SIZE(vl) != Py_SIZE(wl) && (op == Py_EQ || op == Py_NE)) {
        /* Shortcut: if the lengths differ, the lists differ */
        if (op == Py_EQ)
            Py_RETURN_FALSE;
        else
            Py_RETURN_TRUE;
    }

    /* Search for the first index where items are different */
    for (i = 0; i < Py_SIZE(vl) && i < Py_SIZE(wl); i++) {
        PyObject *vitem = vl->ob_item[i];
        PyObject *witem = wl->ob_item[i];
        if (vitem == witem) {
            continue;
        }

        Py_INCREF(vitem);
        Py_INCREF(witem);
        int k = PyObject_RichCompareBool(vitem, witem, Py_EQ);
        Py_DECREF(vitem);
        Py_DECREF(witem);
        if (k < 0)
            return NULL;
        if (!k)
            break;
    }

    if (i >= Py_SIZE(vl) || i >= Py_SIZE(wl)) {
        /* No more items to compare -- compare sizes */
        Py_RETURN_RICHCOMPARE(Py_SIZE(vl), Py_SIZE(wl), op);
    }

    /* We have an item that differs -- shortcuts for EQ/NE */
    if (op == Py_EQ) {
        Py_RETURN_FALSE;
    }
    if (op == Py_NE) {
        Py_RETURN_TRUE;
    }

    /* Compare the final item again using the proper operator */
    return PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op);
}

这是一个名为list_richcompare的函数,用于比较两个Python列表是否相等。下面是这个函数的具体实现:

  1. 定义两个PyListObject指针vl和wl,用于表示输入的两个Python列表。
  2. 检查v和w是否都是Python列表类型。如果其中一个不是Python列表类型,则返回Py_RETURN_NOTIMPLEMENTED。
  3. 将v和w强制转换为PyListObject类型,并将它们分别赋值给vl和wl。
  4. 如果两个列表的长度不同,并且比较操作是相等或不等操作,那么可以快速确定它们不相等,返回Py_RETURN_FALSE或Py_RETURN_TRUE。
  5. 使用for循环从前往后遍历列表vl和wl中的所有元素,找到第一个不相等的元素。
  6. 如果所有元素都相等,而且列表的长度相同,则返回Py_RETURN_RICHCOMPARE(Py_SIZE(vl), Py_SIZE(wl), op)。
  7. 如果找到了不相等的元素,则根据比较操作op返回一个新的PyObject对象,用于表示两个列表的比较结果。

总体来说,list_richcompare函数的作用是比较两个Python列表是否相等。它首先检查输入参数是否正确,然后遍历两个列表中的所有元素,找到第一个不相等的元素,并根据比较操作op返回一个新的PyObject对象,用于表示两个列表的比较结果。这个函数通常会被Python解释器调用,用于支持Python列表的比较操作

列表内置方法


static PyMethodDef list_methods[] = {
    {"__getitem__", (PyCFunction)list_subscript, METH_O|METH_COEXIST, "x.__getitem__(y) <==> x[y]"},
    LIST___REVERSED___METHODDEF
    LIST___SIZEOF___METHODDEF
    LIST_CLEAR_METHODDEF
    LIST_COPY_METHODDEF
    LIST_APPEND_METHODDEF
    LIST_INSERT_METHODDEF
    LIST_EXTEND_METHODDEF
    LIST_POP_METHODDEF
    LIST_REMOVE_METHODDEF
    LIST_INDEX_METHODDEF
    LIST_COUNT_METHODDEF
    LIST_REVERSE_METHODDEF
    LIST_SORT_METHODDEF
    {"__class_getitem__", (PyCFunction)Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
    {NULL,              NULL}           /* sentinel */
};

这是一个名为list_methods的数组,它包含了Python列表对象支持的所有方法。下面是这个数组的具体实现:

  1. "getitem"方法:用于根据索引返回列表中的元素。具体实现中,它调用list_subscript函数,并将列表对象和索引作为参数传入。
  2. LIST___REVERSED___METHODDEF:该宏定义一个名为"reversed"的方法,用于返回一个逆序迭代器。具体实现中,它调用list_reverse和PyObject_GetIter函数,返回一个新的逆序迭代器对象。
  3. LIST___SIZEOF___METHODDEF:该宏定义一个名为"sizeof"的方法,用于返回列表对象占用的内存大小。具体实现中,它调用list___sizeof___impl函数。
  4. LIST_CLEAR_METHODDEF:该宏定义一个名为"clear"的方法,用于清空列表中的所有元素。具体实现中,它调用list_clear函数。
  5. LIST_COPY_METHODDEF:该宏定义一个名为"copy"的方法,用于返回一个新的列表对象,包含原列表中的所有元素。具体实现中,它调用list_copy函数,返回一个新的列表对象。
  6. LIST_APPEND_METHODDEF:该宏定义一个名为"append"的方法,用于在列表的末尾添加一个元素。具体实现中,它调用list_append函数。
  7. LIST_INSERT_METHODDEF:该宏定义一个名为"insert"的方法,用于在列表中的指定位置插入一个元素。具体实现中,它调用list_insert函数。
  8. LIST_EXTEND_METHODDEF:该宏定义一个名为"extend"的方法,用于将一个可迭代对象中的所有元素添加到列表的末尾。具体实现中,它调用list_extend函数。
  9. LIST_POP_METHODDEF:该宏定义一个名为"pop"的方法,用于移除并返回列表中指定位置的元素。具体实现中,它调用list_pop函数。
  10. LIST_REMOVE_METHODDEF:该宏定义一个名为"remove"的方法,用于移除列表中第一个与指定值相等的元素。具体实现中,它调用list_remove函数。
  11. LIST_INDEX_METHODDEF:该宏定义一个名为"index"的方法,用于返回列表中第一个与指定值相等的元素的索引。具体实现中,它调用list_index函数。
  12. LIST_COUNT_METHODDEF:该宏定义一个名为"count"的方法,用于返回列表中与指定值相等的元素数量。具体实现中,它调用list_count函数。
  13. LIST_REVERSE_METHODDEF:该宏定义一个名为"reverse"的方法,用于将列表中的元素倒序排列。具体实现中,它调用list_reverse函数。
  14. LIST_SORT_METHODDEF:该宏定义一个名为"sort"的方法,用于将列表中的元素进行排序。具体实现中,它调用list_sort函数,该函数是一个静态函数,实现了Python列表对象的快速排序算法。具体实现中,它使用了经典的快速排序算法,将列表中的元素按照指定的比较函数进行排序。
  15. "class_getitem"方法:用于支持泛型类型。具体实现中,它调用Py_GenericAlias函数,并返回一个新的泛型别名对象。
  16. NULL:这是一个标志,用于标记方法列表的末尾。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/419469.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vulnhub DC:3.2渗透笔记

kali ip :192.168.20.130 靶机下载地址:https://www.vulnhub.com/entry/dc-32,312/ 信息收集 扫描靶机ip以及开放端口 开放了80端口访问一下 Welcome to DC-3. This time, there is only one flag, one entry point and no clues. To get the flag, youll obviously have …

【Java版oj】day29求正数数组的最小不可组成和、有假币

目录 一、求正数数组的最小不可组成和 &#xff08;1&#xff09;原题再现 &#xff08;2&#xff09;问题分析 &#xff08;3&#xff09;完整代码 二、有假币 &#xff08;1&#xff09;原题再现 &#xff08;2&#xff09;问题分析 &#xff08;3&#xff09;完整代码…

三、用户与权限管理

五、角色管理 1、角色的理解 引入角色的目的时方便管理相同权限的用户。只需要给相同权限的用户分配角色即可&#xff0c;而不需要分配具体的权限 2、创建角色 创建角色使用 CREATE ROLE 语句&#xff0c;语法如下&#xff1a; CREATE ROLE role_name[host_name] [,role_…

干货分享 | 常用车载总线CAN、CANFD、LIN、FlexRay 和 Ethernet概述

随着现代汽车的电子化程度越来越高&#xff0c;汽车总线系统也变得越来越复杂。汽车总线测试是一项重要的任务&#xff0c;它有助于确定车辆电子系统中的问题&#xff0c;并保障车辆的安全和可靠性。本文将介绍五种常见的汽车总线系统和相关的测试工具。 CAN总线 …… 控制器…

传输线的物理基础(八):用近似值和二维场计算特性阻抗

设计一个特定的目标特性阻抗实际上是调整线宽、电介质厚度和介电常数的问题。如果我们知道传输线的长度和导体周围材料的介电常数&#xff0c;并且我们可以计算出特征阻抗&#xff0c;我们就可以使用上面的关系来计算所有其他参数。 当然&#xff0c;每一种不同类型的横截面几…

kaggle竞赛 - Stable Diffusion - Image to Prompts

演绎提示&#xff0c;生成我们的“高度详细&#xff0c;锐利的焦点&#xff0c;插图&#xff0c;宏伟&#xff0c;史诗”图像的3d渲染 1.比赛目标 这个竞赛的目标不是从文本提示生成图像&#xff0c;而是创建一个模型&#xff0c;可以在给定生成图像的情况下预测文本提示&…

曲线平滑算法:三次Hermite曲线生成

目录 1.三次Hermite曲线的参数方程 2. 三次Hermite曲线的绘制 Hermite曲线是通过给定曲线的两个端点的位置矢量、以及两个端点处的切线矢量、来描述曲线的&#xff0c;如图1所示。这里先对Hermite曲线进行数学公式推导&#xff0c;然后讲述如何绘制Hermite曲线。&#xff08;这…

【Ansys】什么软件模块是DS,它和workbench、mechanical的区别在哪里?

一、DesignSpace和workbench 早期的Workbench称之为DesignSpace&#xff0c;更偏向于建模。 现在DS是license的一种&#xff0c;而分析的模块在11中称之为Simulation&#xff08;Design Simulation&#xff09;&#xff0c;在12中改名为Mechanical。 所以&#xff0c;你可以…

SpringBoot整合RabbitMQ(六种工作模式介绍)

介绍 RabbitMQ是一种消息中间件&#xff0c;用于处理来自客户端的异步消息。服务端将要发送的消息放入到队列池中。接收端可以根据RabbitMQ配置的转发机制接收服务端发来的消息。 RabbitMQ依据指定的转发规则进行消息的转发、缓冲和持久化操作&#xff0c;主要用在多服务器间或…

Unity开发数字化看板-通用的设备运动同步

通用的设备运动同步 通过获取实时采集运动位置&#xff0c;发送到unity程序中&#xff0c;通过比例运算&#xff0c;转换成模型的运动位置&#xff0c;实现虚实同步。 在工业设备中&#xff0c;复杂的运动进行分析、分解&#xff0c;最本质的的运动就是平移和转动&#xff0c…

美团到店暑期实习Java一面

目录1.rabbitmq如何避免消息丢失 &#xff08;三个阶段&#xff09;2.如何保证消息的顺序性3.如何保证消息不被重复消费4.缓存与数据库的不一致性5.redis的过期策略和内存淘汰策略6.简单说下LRU的实现7.用原生redis实现分布式锁&#xff0c;锁误删的情况8.锁续期如何去考量9.缓…

MySQL-----库的操作

文章目录前言一、创建数据库二、创建数据库实例三、字符集和校验规则1.查看系统默认字符集以及校验规则.2.查看数据库支持的字符集3.查看数据库支持的字符集校验规则4.校验规则对数据库的影响四、操纵数据库1.查看数据库2.显示创建语句4.修改数据库5.删除数据库6.备份和恢复6.1…

Diffusion模型系列文章

DDPM 论文 扩散模型包括两个过程&#xff1a;前向过程&#xff08;forward process&#xff09;和反向过程&#xff08;reverse process&#xff09;&#xff0c;其中前向过程又称为扩散过程&#xff08;diffusion process&#xff09;&#xff0c;如下图所示&#xff0c;从x…

【音视频第8天】mediasoup拥塞控制【未完待续】

WebRTC的拥塞控制方式主要有以下几个&#xff1a;Transport-cc、BBR-congestion、remb&#xff08;BBR已被google从webrtc移除了&#xff09;。mediasoup支持Transport-cc和remb。 一、前言 实时通信的延时指标 视频服务质量指标 音视频服务质量与带宽之间的矛盾、实时性与服…

【微信小程序】初识微信小程序组件

作者简介&#xff1a;一名C站萌新&#xff0c;前来进行小程序的前进之路博主主页&#xff1a;大熊李子&#x1f43b; 一、组件的创建与引用 1.1 创建组件 在项目的根目录中&#xff0c;鼠标右键&#xff0c;创建 components -> test 文件夹在新建的 components -> test…

NLP / LLMs中的Temperature 是什么?

ChatGPT, GPT-3, GPT-3.5, GPT-4, LLaMA, Bard等大型语言模型的一个重要的超参数 大型语言模型能够根据给定的上下文或提示生成新文本&#xff0c;由于神经网络等深度学习技术的进步&#xff0c;这些模型越来越受欢迎。可用于控制生成语言模型行为的关键参数之一是Temperature …

[译]自下而上认识Elasticsearch

注意:原文发表时间是13年,所以实现有可能与新版不一致. 原文地址:https://www.elastic.co/cn/blog/found-elasticsearch-from-the-bottom-up Introduction 在本系列文章中,我们从一个新的视角来看ElasticSearch.我们将从下往上,从抽象的底层实现到用户可见层,我们在向上移动的…

【JaveEE】网络编程之TCP套接字、UDP套接字

目录 1.网络编程的基本概念 1.1为什么需要网络编程 1.2服务端与用户端 1.3网络编程五元组 1.4套接字的概念 2.UDP套接字编程 2.1UDP套接字的特点 2.2UDP套接字API 2.2.1DatagramSocket类 2.2.2DatagramPacket类 2.2.3基于UDP的回显程序 2.2.4基于UDP的单词查询 …

免疫力低会怎么样 什么情况会导致免疫降低

都说免疫力是很重要的&#xff0c;它会我们健康的第一道防线&#xff0c;但是当免疫力降低的时候&#xff0c;会出现哪些情况&#xff1f;为什么免疫力会降低&#xff1f; 免疫力是人体的防御系统&#xff0c;就像是维持人体正常运转的军队。免疫力的高低&#xff0c;一定程度上…

再探pytorch的Dataset和DataLoader

本文参加新星计划人工智能(Pytorch)赛道&#xff1a;https://bbs.csdn.net/topics/613989052本文从分类、检测、分割三大任务的角度来剖析pytorch得dataset和dataloader源码&#xff0c;可以让初学者深刻理解每个参数的由来和使用&#xff0c;并轻松自定义dataset。思考&#x…