Python 3方法list.clear()
的复杂性是什么?
在documentation中,它被认为与del
a[:]
等效,但我不知道这个函数本身的复杂性。是
它是O(n)
还是O(1)
?
我看了listobject.c
。发现了这个。
int
PyList_ClearFreeList(void)
{
PyListObject *op;
int ret = numfree;
while (numfree) {
op = free_list[--numfree];
assert(PyList_CheckExact(op));
PyObject_GC_Del(op);
}
return ret;
}
这似乎是O(n)
,但我不确定这是否是正确的代码。
我正在开发一个具有性能需求的程序,其中列表被反复填充和清空,我正在尝试找到清空它的最佳方法(因为只有一种方法可以填充它) 。
如果此功能为O(n)
,我只会每次创建一个新列表,这有自己的成本,但我不知道更好方式。
我想到的另一个问题是Python有一个垃圾收集器,所以如果我不释放这些对象(每次都创建新列表,通过重新分配变量名来让另一个无人看管),Python会删除背景(我不确定这些信息),所以我不会使用上述任何方法获得速度,因为结果是相同的。
感谢任何知识。感谢。
答案 0 :(得分:2)
您找到的函数与 Python 中的 list.clear()
无关。您需要的是 _list_clear(PyListObject *a)
,它可以在 here 中找到。
因此,如果您查看该方法的实现,则如下所示:
...
static int
_list_clear(PyListObject *a)
{
Py_ssize_t i;
PyObject **item = a->ob_item;
if (item != NULL) {
/* Because XDECREF can recursively invoke operations on
this list, we make it empty first. */
i = Py_SIZE(a);
Py_SIZE(a) = 0;
a->ob_item = NULL;
a->allocated = 0;
while (--i >= 0) {
Py_XDECREF(item[i]);
}
PyMem_FREE(item);
}
/* Never fails; the return value can be ignored.
Note that there is no guarantee that the list is actually empty
at this point, because XDECREF may have populated it again! */
return 0;
}
...
然而,最重要的一行是检索列表大小的一行:
i = Py_SIZE(a);
还有那些,你要删除一个元素:
...
while (--i >= 0) {
Py_XDECREF(item[i]);
}
...
由于 Py_XDECREF
的性能不依赖于列表的大小,我们可以将其视为常数或 O(1)。由于 Py_XDECREF
被称为列表时间的大小,因此整体时间复杂度是线性的,因此 _list_clear
的时间复杂度为 O(n)。
正如@superbrain 所指出的,对于某些元素,Py_XDECREF
可能会变得非常“重”(由于可能的递归调用),尽管它与输入大小没有直接关系,但我们可以通过引入参数 e
- 减少元素引用计数的总成本。在这种解释中,总时间复杂度为 O(n+e)。
答案 1 :(得分:0)
过早优化......和XY problems ...
也许最好的方法更务实?编写程序,看看是否需要额外的性能。然后测量您列出的不同选项,并选择更快的选项。
O()
符号见解可能会或可能不会转化为性能,尤其是在不同级别执行不同操作的python中。
关于您的具体问题:
创建新列表并让垃圾收集器完成其工作可以说是更清晰
但是,列表是可自动调整大小的对象,它们在分摊的时间内运行。如果您的计划对性能至关重要,您可能需要考虑更专业的结构,例如array
,numpy.array
或c structs
?