2012-05-23 12 views
13

documentation mówi, że funkcja produkt kartezjańskiPythona

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

Jak to może być możliwe z generatorów? Czy ktoś może mi pokazać przykład z ograniczonym zużyciem pamięci dla 2 generatorów?

+3

Możliwy duplikat [Dlaczego otrzymuję błąd MemoryError w itertools.product?] (Http://stackoverflow.com/q/8695422/222914) –

Odpowiedz

9

Patrząc na kod źródłowy modułu, itertools.product() rzeczywiście przekształca każdy argument do krotki:

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

Innymi słowy, zużycie pamięci itertools.product() „s wydaje się być liniowy w rozmiarze argumentów wejściowych.

4

Cóż, mówi także:

Zagnieżdżone pętle cykl jak liczniku ze skrajnego prawego elementu postęp w każdej iteracji. Ten wzór tworzy uporządkowanie leksykograficzne, więc jeśli dane wejściowe są sortowane, krotki produktu są emitowane w posortowanej kolejności.

To dość dużo, jak to działa w realizacji (Modules/itertoolsmodule.c)

Oto obiekt stanu:

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; 

I następny element jest zwracany przez funkcję product_next, który wykorzystuje ten stan i algorytm opisany w cytacie do generowania następnego stanu. Zobacz this answer, aby poznać wymagania dotyczące pamięci.

W zakresie edukacji ogólnej można przeczytać o tym, jak tworzyć generatory ze stanem z rozszerzeń C here.