Python

2012-05-23 17 views
13

El documentation dice que la función del producto cartesianoPython

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

¿Cómo puede ser eso posible con los generadores? ¿Alguien puede mostrarme un ejemplo con un consumo de memoria limitado para 2 generadores?

+3

Posible duplicado de [¿Por qué obtengo un MemoryError con itertools.product?] (Http://stackoverflow.com/q/8695422/222914) –

Respuesta

9

Mirando el código fuente del módulo, itertools.product() realidad convierte cada argumento a una tupla:

// 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; 
} 

En otras palabras, el consumo de memoria itertools.product() 's parece ser lineal en el tamaño de los argumentos de entrada.

4

Bueno, también dice:

El ciclo de bucles anidados como un odómetro con el elemento más a la derecha avanzar en cada iteración. Este patrón crea un orden lexicográfico de de modo que si los iterables de la entrada están ordenados, las tuplas del producto se emiten en orden ordenado.

Esto es más o menos cómo funciona en la aplicación (Modules/itertoolsmodule.c)

Aquí es el objeto de estado:

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; 

Y el siguiente artículo es devuelto por la función product_next, que utiliza esta estado y el algoritmo descrito en la cita para generar el siguiente estado. Consulte this answer para comprender los requisitos de memoria.

Para la educación general, puede leer acerca de cómo crear generadores con estado desde las extensiones C here.