2011-12-05 11 views
33

He leído que en CPython, la pila de intérpretes (la lista de funciones de Python llamada para llegar a este punto) se mezcla con la pila C (la lista de funciones C que se llamaron en el propio código del intérprete). Si es así, ¿cómo se implementan los generadores y coroutines? ¿Cómo recuerdan su estado de ejecución? ¿CPython copia la pila de cada generador/coroutine desde y hacia una pila de SO? ¿O CPython simplemente mantiene el marco de pila superior del generador en el montón, ya que el generador solo puede ceder desde ese marco superior?¿Cómo se implementan los generadores y coroutines en CPython?

+8

Me respondí accidentalmente casi cuatro años después al ser coautor de un capítulo que incluye una explicación de cómo se implementan los generadores y coroutines: http://aosabook.org/es/500L/a-web-crawler-with-asyncio -coroutines.html –

+0

Artículo excelente, muy denso. –

+0

No relacionado, pero ... ¿cómo conseguiste, en menos de 4 años, preguntar cómo se implementan los generadores y escribir un capítulo de un libro con Guido sobre este tema? :) – max

Respuesta

14

La instrucción yield toma el contexto de ejecución actual como un cierre, y lo transforma en un objeto vivo propio. Este objeto tiene un método __iter__ que continuará después de esta declaración de rendimiento.

Así que la pila de llamadas se transforma en un objeto de montón.

+3

Es importante aclarar que la pila de C "hardware" y la pila de Python son completamente diferentes, ya que la pregunta confunde a ambos. Mi respuesta aclara esto. (@Rudi - tu respuesta está bien, dejo el comentario para que otras personas que llegan comprueben esa parte también) – jsbueno

37

La noción de que la pila de Python y la pila C en un programa en ejecución de Python están entremezcladas puede ser engañosa.

La pila de Python es algo completamente separado de la pila de C real utilizada por el intérprete. Las estructuras de datos en la pila de Python son en realidad objetos completos de "marco" de Python (que incluso pueden ser inspeccionados y tienen algunos atributos modificados en tiempo de ejecución). Esta pila es administrada por la máquina virtual de Python, que se ejecuta en C y tiene un programa C normal, nivel de máquina, pila.

Al usar generadores e iteradores, el intérprete simplemente almacena el objeto de cuadro respectivo en otro lugar que no sea en la pila de programas de Python, y lo empuja hacia atrás cuando se reanuda la ejecución del generador. Este "otro lugar" es el propio objeto generador. Llamar al método "siguiente" o "enviar" al objeto generador hace que esto ocurra.

+1

Este es el tipo de respuesta técnica que deseo ver más en StackOverflow. ¡Gracias! – glendon

+2

Lo busqué después de leer esto, así que si alguien más está interesado, aquí está [la implementación de generadores CPython] (https://github.com/python/cpython/blob/master/Objects/genobject.c). Recomiendo leer esta respuesta primero, ayuda a entender lo que hace el código. – spectras

-2

Algunas respuestas existentes y comentarios afirman que Python mantiene una "pila de programas" que está completamente separada de la pila C de la VM. Esta afirmación es incorrecta.

Comprobar el enlace: http://en.wikipedia.org/wiki/Stackless_Python

Stackless Python existe pero no es corriente principal. El entendimiento es que la pregunta es correcta.

Cuestiones relacionadas