2011-12-05 19 views
33

Ho letto che in CPython, lo stack dell'interprete (l'elenco delle funzioni Python chiamate per raggiungere questo punto) è mescolato con lo stack C (l'elenco delle funzioni C che sono state chiamate nel codice proprio dell'interprete). Se è così, allora come vengono implementati i generatori e le coroutine? Come si ricordano il loro stato di esecuzione? CPython copia lo stack di ogni generatore/coroutine su e da uno stack del sistema operativo? Oppure CPython mantiene semplicemente il frame dello stack più in alto del generatore sull'heap, dal momento che il generatore può cedere solo dal frame più in alto?Come vengono implementati generatori e coroutine in CPython?

+8

Ho accidentalmente risposto a me stesso quasi quattro anni dopo co-autore di un capitolo che include una spiegazione su come sono implementati generatori e coroutine: http://aosabook.org/en/500L/a-web-crawler-with-asyncio -coroutines.html –

+0

Ottimo articolo, molto denso. –

+0

Non correlato, ma ... come sei riuscito, in meno di 4 anni, a chiedere come sono stati implementati i generatori per scrivere un capitolo di un libro con Guido su questo argomento? :) – max

risposta

14

L'istruzione yield prende l'attuale contesto di esecuzione come chiusura e la trasforma in un oggetto vivente. Questo oggetto ha un metodo __iter__ che continuerà dopo questa dichiarazione di rendimento.

Quindi lo stack di chiamate viene trasformato in un oggetto heap.

+3

È importante chiarire lo stack "hardware" C e lo stack Python sono cose completamente diverse, poiché la domanda confonde entrambi. La mia risposta chiarisce questo. (@Rudi - la tua risposta va bene, sto lasciando il commento in modo che anche altre persone arrivino qui a vedere quella parte) – jsbueno

37

La nozione che lo stack Python e lo stack C in un programma Python in esecuzione vengano mescolati può essere fuorviante.

Lo stack Python è qualcosa di completamente separato rispetto allo stack C utilizzato dall'interprete. Le strutture dati sullo stack Python sono in effetti oggetti "frame" Python completi (che possono anche essere introspected e avere alcuni attributi modificati in fase di esecuzione). Questo stack è gestito dalla macchina virtuale Python, che a sua volta viene eseguita in C e quindi ha un normale programma C, livello macchina, stack.

Quando si utilizzano generatori ed iteratori, l'interprete memorizza semplicemente il rispettivo oggetto frame da qualche altra parte rispetto allo stack del programma Python e lo spinge indietro quando riprende l'esecuzione del generatore. Questo "da qualche altra parte" è l'oggetto generatore stesso. Se si fa riferimento al metodo "successivo" o "invia" sull'oggetto generatore, ciò accade.

+1

Questo è il tipo di risposta tecnica che desidero vedere di più in StackOverflow. Grazie! – glendon

+2

L'ho cercato dopo aver letto questo, quindi se qualcun altro è interessato, ecco [implementazione CPython di generatori] (https://github.com/python/cpython/blob/master/Objects/genobject.c). Consiglio di leggere prima questa risposta, aiuta a capire cosa fa il codice. – spectras

-2

Alcune risposte e commenti esistenti sostengono che Python mantiene uno "stack di programmi" completamente separato dallo stack C della VM. Questa affermazione è sbagliata.

Controllare il link: http://en.wikipedia.org/wiki/Stackless_Python

Stackless Python esiste ma non è mainstream. La comprensione è che la domanda è giusta.

Problemi correlati