Подтвердить что ты не робот

Потребление памяти продукта Python itertools

Документация говорит о том, что декартовая функция продукта

the actual implementation does not build up intermediate results in memory.

Как это возможно с генераторами? Может ли кто-нибудь показать мне пример с ограниченным объемом памяти для 2 генераторов?

4b9b3361

Ответ 1

Глядя на исходный код модуля, itertools.product() фактически преобразует каждый аргумент в кортеж:

// product_new() in itertoolsmodule.c
for (i=0; i < nargs ; ++i) {
    PyObject *item = PyTuple_GET_ITEM(args, i);
    PyObject *pool = PySequence_Tuple(item); //<==== Call tuple(arg)
    if (pool == NULL)
        goto error;
    PyTuple_SET_ITEM(pools, i, pool);
    indices[i] = 0;
}

Другими словами, потребление памяти itertools.product() кажется линейным по размеру входных аргументов.

Ответ 2

Ну, это также говорит:

Вложенные циклы цикла, такие как одометр с самым правым элементом продвигаясь на каждой итерации. Этот шаблон создает лексикографический упорядочивая так, чтобы, если итерации входов отсортированы, продукт кортежи испускаются в отсортированном порядке.

Это в значительной степени работает в реализации (Modules/itertoolsmodule.c)

Вот объект состояния:

typedef struct {
    PyObject_HEAD
    PyObject *pools;       /* tuple of pool tuples */
    Py_ssize_t *indices;   /* one index per pool */
    PyObject *result;      /* most recently returned result tuple */
    int stopped;           /* set to 1 when the product iterator is exhausted */
} productobject;

И следующий элемент возвращается функцией product_next, которая использует это состояние и алгоритм, описанный в цитате, для генерации следующего состояния. См. этот ответ, чтобы понять требования к памяти.

Для общего образования вы можете прочитать о том, как создавать генераторы с состоянием из C-расширений здесь.