Python的insert()方法之间的实现和性能差异以及切片

时间:2016-12-24 12:50:21

标签: python performance list insert slice

以下列方式在python列表中插入元素有什么区别?

myList.insert(at, myValue)
myList[at:at] = [myValue]

我已经进行了一些测试,两者的性能非常相似,但切片插件始终会产生稍微好一些的效果。我的问题是关于实施和绩效的差异,而不是行为。

2 个答案:

答案 0 :(得分:1)

我们有相同的行为,见下文:

默认行为是在给定索引处插入项目; 更高指数的每个值都会移动一个位置到最后。

>>> my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> my_list.insert(5, 'item')
>>> my_list
['a', 'b', 'c', 'd', 'e', 'item', 'f', 'g']

>>> my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> my_list.insert(-3, 'item')
>>> my_list
['a', 'b', 'c', 'd', 'item', 'e', 'f', 'g']

如果列表为空,则正常附加项目。

>>> my_list = []
>>> my_list.insert(5, 'item')
>>> my_list
['item']

>>> my_list = []
>>> my_list.insert(-3, 'item')
>>> my_list
['item']

如果索引超出范围,则在索引为正数时将项目附加到末尾,如果为负数则将项目附加到开头。 没有例外。

>>> my_list = ['a', 'b']
>>> my_list.insert(5, 'item')
>>> my_list
['a', 'b', 'item']

>>> my_list = ['a', 'b']
>>> my_list.insert(-3, 'item')
>>> my_list
['item', 'a', 'b']

切片表示法具有完全相同的行为, 在一系列相同索引的情况下:

>>> my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> my_list[5:5] = ['item']
>>> my_list
['a', 'b', 'c', 'd', 'e', 'item', 'f', 'g']

>>> my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> my_list[-3:-3] = ['item']
>>> my_list
['a', 'b', 'c', 'd', 'item', 'e', 'f', 'g']

>>> my_list = []
>>> my_list[5:5] = ['item']
>>> my_list
['item']

>>> my_list = []
>>> my_list[-3:-3] = ['item']
>>> my_list
['item']

>>> my_list = ['a', 'b']
>>> my_list[5:5] = ['item']
>>> my_list
['a', 'b', 'item']

>>> my_list = ['a', 'b']
>>> my_list[-3:-3] = ['item']
>>> my_list
['item', 'a', 'b']

切片表示法与使用__setitem__()对象调用slice方法相同:

>>> my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> my_list.__setitem__(slice(5, 5), ['item'])
>>> my_list
['a', 'b', 'c', 'd', 'e', 'item', 'f', 'g']

答案 1 :(得分:0)

实施细节

根据GitHub在https://github.com/python/cpython/blob/master/Objects/listobject.chttps://github.com/python/cpython/blob/master/Objects/listobject.c上提供的CPython实现,我们有:

.button { display:block; } 方法在以下函数中定义:

insert()

哪个调用static PyObject * listinsert(PyListObject *self, PyObject *args) { Py_ssize_t i; PyObject *v; if (!PyArg_ParseTuple(args, "nO:insert", &i, &v)) return NULL; if (ins1(self, i, v) == 0) Py_RETURN_NONE; return NULL; } 函数,这里是C代码:

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; } 函数完成:

PyList_SetSlice()

优化的实施在:

完成
int
PyList_SetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
{
    if (!PyList_Check(a)) {
        PyErr_BadInternalCall();
        return -1;
    }
    return list_ass_slice((PyListObject *)a, ilow, ihigh, v);
}

插入在以下代码中完成:

static int
list_ass_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)

希望它有所帮助!