La pila de llamadas de las funciones en Python

Imagina que mantienes una conversación interminable con alguien. Hablas de tu amiga Alice, que luego te recuerda una historia sobre tu compañero de trabajo Bob, pero antes tienes que explicar algo sobre tu prima Carol. Terminas tu historia sobre Carol y vuelves a hablar de Bob, y cuando terminas tu historia sobre Bob, vuelves a hablar de Alice. Pero entonces te acuerdas de tu hermano David, así que cuentas una historia sobre él, y luego vuelves a terminar tu historia original sobre Alice. Tu conversación sigue una estructura similar a la de una pila, como en la imagen. La conversación es similar a una pila porque el tema actual siempre está en la parte superior de la pila.

Su pila de conversación divagante

Al igual que nuestra conversación divagante, llamar a una función no envía la ejecución en un viaje de ida a la parte superior de una función. Python recordará qué línea de código llamó a la función para que la ejecución pueda volver allí cuando encuentre una sentencia return. Si esa función original llamara a otras funciones, la ejecución volvería primero a esas llamadas de función, antes de volver de la llamada a la función original.

Abre una ventana del editor de archivos e introduce el siguiente código, guardándolo como abcdCallStack.py:

   def a():
       print('a() starts')
    ➊ b()
    ➋ d()
       print('a() returns')

   def b():
       print('b() starts')
    ➌ c()
       print('b() returns')

   def c():
    ➍ print('c() starts')
       print('c() returns')

   def d():
       print('d() starts')
       print('d() returns')

➎ a()

Si ejecutas este programa, la salida tendrá el siguiente aspecto:

a() starts
b() starts
c() starts
c() returns
b() returns
d() starts
d() returns
a() returns

Puedes ver la ejecución de este programa en https://autbor.com/abcdcallstack/. Cuando se llama a() ➎, se llama a b() ➊, que a su vez llama a c() ➌. La función c() no llama a nada; sólo muestra c() starts ➍ y c() return antes de volver a la línea de b() que la llamó ➌. Una vez que la ejecución vuelve al código en b() que llamó a c(), vuelve a la línea en a() que llamó a b() ➊. La ejecución continúa hasta la siguiente línea en la función b() ➋, que es una llamada a d(). Al igual que la función c(), la función d() tampoco llama a nada. Sólo muestra d() starts y d() returns antes de volver a la línea de b() que la llamó. Como b() no contiene ningún otro código, la ejecución vuelve a la línea en a() que llamó a b() ➋. La última línea en a() muestra a() returns antes de volver a la llamada original de a() al final del programa ➎.

La pila de llamadas es la forma en que Python recuerda dónde devolver la ejecución después de cada llamada a una función. La pila de llamadas no se almacena en una variable de tu programa, sino que Python la maneja entre bastidores. Cuando tu programa llama a una función, Python crea un objeto marco en la parte superior de la pila de llamadas. Los objetos marco almacenan el número de línea de la llamada a la función original para que Python pueda recordar dónde volver. Si se hace otra llamada a una función, Python pone otro objeto marco en la pila de llamadas por encima del otro.

Cuando una llamada a la función regresa, Python elimina un objeto marco de la parte superior de la pila y mueve la ejecución al número de línea almacenado en él. Ten en cuenta que los objetos marco siempre se añaden y eliminan de la parte superior de la pila y no de cualquier otro lugar. La imagen ilustra el estado de la pila de llamadas en abcdCallStack.py a medida que cada función es llamada y devuelve.

Los objetos del marco de la pila de llamadas a medida que abcdCallStack.py llama y retorna las funciones

La parte superior de la pila de llamadas es la función en la que se está ejecutando actualmente. Cuando la pila de llamadas está vacía, la ejecución está en una línea fuera de todas las funciones.

La pila de llamadas es un detalle técnico que no es estrictamente necesario conocer para escribir programas. Es suficiente con entender que las llamadas a funciones vuelven al número de línea desde el que fueron llamadas. Sin embargo, entender las pilas de llamadas facilita la comprensión de los ámbitos local y global, descritos en la siguiente sección.

Deja una respuesta