下面的代碼初始化一個隨機整數串列,并對其進行迭代。給定 a subset_size,在每次迭代i時,i: i subset_size都會訪問 的子串列。訪問子串列的時間隨著subset_size. 對于n = 100000and subset_size = 50000,我的 i5 mbp 需要 15 秒以上。我認為子串列是使用 2 個指標和惰性求值來檢索的,但看起來c幕后有一些回圈填充一個新串列并將其作為結果回傳。這是對實際發生的事情的正確描述還是有其他解釋?
import random
from datetime import timedelta
from time import perf_counter
def example(n, subset_size):
x = [random.randint(0, 10000) for _ in range(n)]
t = perf_counter()
for i in range(n - subset_size):
_ = x[i : i subset_size]
print(timedelta(seconds=perf_counter() - t))
if __name__ == '__main__':
example(100000, 50000)
0:00:15.131059
uj5u.com熱心網友回復:
我認為子串列是使用 2 個指標和惰性求值來檢索的,但看起來幕后有一些 c 回圈填充一個新串列并將其作為結果回傳。
你的假設是正確的。切片串列總是會創建新串列。這是源代碼的相關部分。我添加了一些評論以了解每個步驟的情況。
static PyObject *
list_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
{
PyListObject *np;
PyObject **src, **dest;
Py_ssize_t i, len;
len = ihigh - ilow;
if (len <= 0) {
return PyList_New(0);
}
# create new list which is long enough to hold the slice length elements.
np = (PyListObject *) list_new_prealloc(len);
if (np == NULL)
return NULL;
# Adjust the pointer offset, because list internally uses an array of pointers.
src = a->ob_item ilow;
dest = np->ob_item;
# Copy the elements back.
for (i = 0; i < len; i ) {
PyObject *v = src[i];
Py_INCREF(v);
dest[i] = v;
}
Py_SET_SIZE(np, len);
return (PyObject *)np;
}
正如您所看到的,當您對串列進行切片時,它必須首先呼叫list_new_prealloc這是創建一個空串列并將記憶體分配到切片長度的位置。
static PyObject *
list_new_prealloc(Py_ssize_t size)
{
assert(size > 0);
# Create new list
PyListObject *op = (PyListObject *) PyList_New(0);
if (op == NULL) {
return NULL;
}
assert(op->ob_item == NULL);
# Allocating memory
op->ob_item = PyMem_New(PyObject *, size);
if (op->ob_item == NULL) {
Py_DECREF(op);
return PyErr_NoMemory();
}
op->allocated = size;
return (PyObject *) op;
}
uj5u.com熱心網友回復:
串列切片不是惰性求值,確實會創建一個新的串列物件;例如,參見An Informal Introduction to Python,第 3.1.3 節。串列:
所有切片操作都會回傳一個包含請求元素的新串列。
uj5u.com熱心網友回復:
串列切片不會被延遲評估,串列將在每次迭代時創建。用于itertools.islice創建惰性切片:
islice(x, i, i subset_size)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/533227.html
標籤:Python列表表现索引
