3. Funciones

3.1. Definiciones y uso

En el contexto de la programación una función es una secuencia de sentencias que ejecuta una operación deseada y tiene un nombre. Esta operación se especifica en una definición de función. La sintaxis para una definición de función en Python es:

def NOMBRE( LISTA DE PARAMETROS ):
    SENTENCIAS

Usted puede inventar los nombres que desee para sus funciones siempre y cuando no use una palabra reservada de Python. La lista de parámetros especifica qué información, si es que la hay, se debe proporcionar a fin de usar la nueva función.

Se puede incluir cualquier número de sentencias dentro de la función, pero todas deben sangrarse a partir del margen izquierdo. En los ejemplos de este libro usaremos un sangrado estándar de cuatro espacios. La definición de función es la primera de diversas sentencias compuestas que veremos más adelante, teniendo todas ellas la misma estructura:

  1. Un encabezado, que empieza con una palabra reservada y termina con dos puntos.
  2. Un cuerpo consistente de una o más sentencias de Python, cada una de ellas con la misma sangría – 4 espacios es el estándar de Python – a partir del margen izquierdo.

En una definición de función la palabra reservada en el encabezado es def, y enseguida se escribe el nombre de la función y una lista de parámetros encerrados entre paréntesis. La lista de parámetros puede estar vacía o contener un sinnúmero de parámetros. En cualquier caso los paréntesis se requieren.

El primer par de funciones que escribiremos no tiene parámetros, por lo que la sintaxis luce así:

def nueva_linea():
    print        # la sentencia print sin argumentos muestra una nueva línea

Esta función se llama nueva_linea. Los paréntesis vacíos indican que la función no tiene parámetros. Su cuerpo contiene solamente una única sentencia, cuya salida es una línea vacía. (Eso es lo que ocurre cuando se usa la sentencia print sin argumentos.)

Nota del traductor: El uso de nombres de funciones (y de nombres de variables) con acentos sólo es posible en la versión 3.0 — y superiores — del intérprete de Python. Si tiene alguna versión inferior, no use acentos en los nombres de funciones.

Definir una nueva función no hace que la función se ejecute. Para hacerlo se necesita una llamada a función. Las llamadas a función contienen el nombre de la función a ejecutar seguida por la lista de valores, llamados argumentos, que son asignados a los parámetros en la definición de función. Nuestra primera función tiene una lista vacía de parámetros, por lo que la llamada a función no tiene ningún argumento. Nótese, sin embargo, que en la llamada a función se requiere los paréntesis:

print "Primera Línea."
nueva_linea()
print "Segunda Línea."

La salida de este programa es:

Primera Línea.

Segunda Línea.

El espacio extra entre las dos líneas es el resultado de la llamada a la función nueva_linea(). ¿Qué pasa si deseamos más espacio entre las líneas? Podemos llamar la misma función repetidamente:

print "Primera Línea."
nueva_linea()
nueva_linea()
nueva_linea()
print "Segunda Línea."

O podemos escribir una nueva función llamada tres_líneas que muestre tres nuevas líneas:

def tres_lineas():
    nueva_linea()
    nueva_linea()
    nueva_linea()

print "Primera Línea."
tres_lineas()
print "Segunda Línea."

Esta función contiene tres sentencias, y todas están sangradas por cuatro espacios. Como la siguiente sentencia no está sangrada, Python reconoce que tal sentencia no es parte de la función.

Hay que destacar algunos aspectos de este programa:

  • Usted puede llamar la misma función repetidamente. De hecho, es una práctica muy común y útil.
  • Usted puede llamar una función dentro de otra función; en este caso tres_líneas llama a nueva_linea().

Hasta este punto, puede que no parezca claro por qué hay que tomarse la molestia de crear todas estas funciones. De hecho, hay muchas razones, y el ejemplo que acabamos de ver muestra dos:

  1. Crear una nueva función le da a usted la oportunidad de nombrar un grupo de sentencias. Las funciones pueden simplificar un programa escondiendo un cálculo complejo detrás de un comando único que usa palabras en lenguaje natural, en lugar de un código arcano.
  2. Crear una nueva función puede recortar el tamaño de un programa eliminando el código repetitivo. Por ejemplo, una forma más corta de mostrar nueve líneas consecutivas consiste en llamar la función tres_líneas tres veces.

Así, juntando los fragmentos de código de los párrafos previos en un guión llamado pruebame1.py, el programa completo luce como sigue:

def nueva_linea():
    print

def tres_lineas():
    nueva_linea()
    nueva_linea()
    nueva_linea()

print "Primera Línea."
tres_lineas()
print "Segunda Línea."

Este programa contiene dos definiciones de función: nueva_linea y tres_líneas. Las definiciones de función se ejecutan como las otras sentencias, pero su efecto es crear nuevas funciones. Las sentencias dentro de la función no se ejecutan hasta que la función sea llamada, y la definición de función no genera salida.

Como usted puede imaginar, se tiene que crear una función antes de ejecutarla. En otras palabras, la definición de función tiene que ejecutarse antes de llamarla por primera vez.

3.2. Flujo de ejecución

Con el fin de asegurar que una función se defina antes de su primer uso usted tiene que saber el orden en el que las sentencias se ejecutan, este orden de ejecución se denomina flujo de ejecución.

La ejecución siempre empieza con la primera sentencia del programa. Las sentencias se ejecutan una a una, desde arriba hacia abajo.

Las definiciones de función no alteran el flujo de ejecución del programa, pero recuerde que las sentencias que están dentro de las funciones no se ejecutan hasta que éstas sean llamadas. Aunque no es muy común, usted puede definir una función dentro de otra. En este caso, la definición interna no se ejecuta hasta que la función externa sea llamada.

Las llamadas a función son como un desvío en el flujo de ejecución. En lugar de continuar con la siguiente sentencia, el flujo salta a la primera línea de la función llamada, ejecuta todas las sentencias de la función, y regresa para continuar donde estaba previamente.

Esto suena sencillo, hasta que tenemos en cuenta que una función puede llamar a otra. Mientras se está ejecutando una función, el programa puede ejecutar las sentencias de otra función. Pero, mientras se está ejecutando la nueva función, el programa puede tener que ejecutar ¡otra función!

Afortunadamente, Python es experto en hacer el seguimiento de sus movimientos, así que cada vez que una función termina, el programa regresa al punto de la función desde donde fue llamada la función que recien fue terminada. Cuando llega al fin del programa, la ejecución termina.

¿Cual es la moraleja de esta sórdida historia? Cuando lea un programa, no lo haga de arriba hacia abajo. En lugar de esto, siga el flujo de ejecución.

3.3. Parámetros, argumentos y la sentencia import

La mayoría de las funciones requieren argumentos, los valores que controlan la manera en que la funciones trabajan. Por ejemplo, si usted quiere encontrar el valor absoluto de un número, tiene que indicar cuál es el número. Python tienen una función integrada en su biblioteca de funciones para calcular el valor absoluto:

>>> abs(5)
5
>>> abs(-5)
5

En este ejemplo los argumentos de la función abs son 5 y -5.

Algunas funciones necesitan más de un argumento. Por ejemplo la función de biblioteca pow toma dos argumentos, la base y el exponente. Dentro de la función, los valores que se pasan se asignan a variables llamadas parámetros.

>>> pow(2, 3)
8
>>> pow(7, 4)
2401

Otra función de biblioteca que toma más de un argumento es max.

>>> max(7, 11)
11
>>> max(4, 1, 17, 2, 12)
17
>>> max(3 * 11, 5**3, 512 - 9, 1024**0)
503

La función max puede enviar a la definición de función cualquier número de argumentos, separados por comas, y la llamada a función devolverá el máximo de los valores enviados. Los argumentos pueden ser valores simples o expresiones. En el último ejemplo la llamada a función regresa 503, puesto que es el mayor de 33, 125 y 1.

Aquí hay un ejemplo de una función definida por el programador que toma un parámetro:

def muestra_doble(bruno):
    print bruno, bruno

Esta función toma un sólo argumento y lo asigna a un parámetro llamado bruno. El valor del parámetro (en este momento no tenemos idea de lo que será) se muestra dos veces seguido por un salto de línea. El nombre bruno se escogió para sugerir que el nombre que se le asigna a un parámetro depende de usted; pero, en general, usted deseará escoger algo más apropiado que bruno.

La línea de comandos de Python nos proporciona una forma apropiada de probar nuestras funciones. Podemos usar la sentencia import para traer las funciones — que hemos definido en un guión — a la sesión del intérprete de Python. Para saber cómo funciona considere que la función muestra_doble está definida en un guión llamado cap03.py. Podemos probarla interactivamente importándola en nuestra sesión de la línea de comandos de Python:

>>> from cap03 import *
>>> muestra_doble('Basura')
Basura Basura
>>> muestra_doble(5)
5 5
>>> muestra_doble(3.14159)
3.14159 3.14159

En una llamada a función el valor del argumento se asigna al parámetro correspondiente en la definición de función. En efecto, esto sucede si se ejecuta bruno = 'Basura' cuando la función muestra_doble('Basura') es llamada, ó cuando se ejecuta bruno = 5 en muestra_doble(5), ó bruno = 3.14159 en muestra_doble(3.14159).

Cualquier tipo de argumento que pueda ser mostrado, puede ser enviado a la función muestra_doble. En la primera llamada a función el argumento es una cadena. En la segunda es un entero. En la tercera es un número de punto flotante (tipo float).

De la misma manera que con las funciones de biblioteca, podemos usar una expresión como argumento para la función muestra_doble:

>>> muestra_doble('Basura' * 4)
BasuraBasuraBasuraBasura BasuraBasuraBasuraBasura

Primero se evalúa 'Basura' * 4 para producir 'BasuraBasuraBasuraBasura', el cual se pasa como un argumento a la función muestra_doble.

3.4. Composición

Asi como las funciones matemáticas, las funciones de Python pueden componerse, esto es, puede usar el resultado de una función como entrada de otra

>>> muestra_doble(abs(-7))
7 7
>>> muestra_doble(max(3, 1, abs(-11), 7))
11 11

En el primer ejemplo, abs(-7) produce 7, el cual es ahora el argumento de la función muestra_doble. En el segundo ejemplo tenemos dos niveles de composición puesto que primero se evalúa abs(-11) que produce 11, y luego se evalúa max(3, 1, 11, 7) que da como resultado 11; finalmente la función muestra_doble(11) muestra el resultado.

También podemos usar una variable como un argumento:

>>> miguel = 'Eric, el medio abeja.'
>>> muestra_doble(miguel)
Eric, el medio abeja. Eric, el medio abeja.

Note algo muy importante en este ejemplo: el nombre de la variable que pasamos como argumento (miguel) no tiene nada que ver con el nombre del parámetro (bruno). Es decir, no importa cómo se nombraba el valor originalmente (desde la llamada de función); aquí, en la función muestra_doble llamamos a cualquiera de ellos bruno.

3.5. Las variables y los parámetros son locales

Cuando usted crea una variable local en una función, solamente existe dentro de la función y no fuera de ella. Por ejemplo:

def concatena_doble(parte1, parte2):
    concatena = parte1 + parte2
    muestra_doble(concatena)

Esta función toma dos argumentos, los concatena, y luego muestra el resultado dos veces. Podemos llamar a la función con dos cadenas:

>>> cantico1 = "Pie Jesu domine, "
>>> cantico2 = "Dona eis requiem."
>>> concatena_doble(cantico1, cantico2)
Pie Jesu domine, Dona eis requiem. Pie Jesu domine, Dona eis requiem.

Cuando concatena_doble termina, la variable concatena se destruye. Si intentamos mostrarla obtenemos un error:

>>> print concatena
NameError: name 'concatena' is not defined

Los parámetros también son locales. Por ejemplo, afuera de la función muestra_doble, no existe algo como bruno. Si usted intenta usarlo Python se quejará.

3.6. Diagramas de pila

Para seguir la pista de qué variables se usan en qué lugares es útil dibujar un diagrama de pila. Como los diagramas de estado, los diagramas de pila muestran el valor de cada variable y además muestran a qué función pertenece cada una.

Cada función se representa por un marco. Un marco es una recuadro con el nombre de una función al lado y los parámetros y variables adentro. El diagrama de pila para el ejemplo anterior luce así:

El orden de la pila mustra el flujo de ejecución. La función muestra_doble fue llamada por concatena_doble, y concatena_doble fue llamada por __main__, que es un nombre especial para la función de más alto nivel. Esto significa que cuando usted crea una variable afuera de cualquier función, tal variable pertenece a __main__.

Cada parámetro se refiere al mismo valor que su argumento correspondiente. Así, parte1 tiene el mismo valor que cantico1, parte2 tiene el mismo valor que cantico2, y bruno tiene el mismo valor que concatena.

Si sucede un error durante una llamada de función, Python muestra el nombre de ésta, el nombre de la función que la llamó, el nombre de la función que llamó a esta otra, y así sucesivamente hasta llegar a la función de más alto nivel.

Para ver cómo funciona esto cree un guión en Python que se llame pruebame2.py que luce como sigue:

def muestra_doble(bruno):
    print bruno, bruno
    print concatena

def concatena_doble(parte1, parte2):
    concatena = parte1 + parte2
    muestra_doble(concatena)

cantico1 = "Pie Jesu domine, "
cantico2 = "Dona eis requim."
concatena_doble(cantico1, cantico2)

Hemos agregado la sentencia print concatena en la función muestra_doble; sin embargo, concatena no está definida en esta función. Al ejecutar este guión se producirá un mensaje de error como el siguiente:

Traceback (innermost last):
  File "pruebame2.py", line 11, in <module>
    concatena_doble(cántico1, cántico2)
  File "pruebame2.py", line 7, in concatena_doble
    muestra_doble(concatena)
  File "pruebame2.py", line 3, in muestra_doble
    print concatena
NameError: global name 'concatena' is not defined

Esta lista de funciones se denomina trazado inverso. Nos informa en qué archivo de programa ocurrió el error, en qué línea, y qué funciones se estaban ejecutando en ese momento. También muestra la línea de código que causó el error.

Note la similitud entre el trazado inverso y el diagrama de pila. Esto no es una coincidencia. De hecho, otro nombre común para el trazado inverso es trazado de pila.

3.7. Glosario

función
Secuencia de sentencias etiquetadas que llevan a cabo determinada operación de utilidad. Las funciones pueden tomar parámetros o no, y pueden producir un resultado o no.
definición de función
Sentencia que crea una nueva función, especificando su nombre, parámetros y las sentencias que ejecuta.
sentencia compuesta

Sentencia que consiste de dos partes:

  1. encabezado - que empieza con una palabra reservada que determina el tipo de sentencia, y finaliza con dos puntos.
  2. cuerpo - que contiene una o más sentencias con el mismo sangrado desde el encabezado.

La sintaxis de una sentencia compuesta se ve así:

.. sourcecode:: python
palabra_reservada expresión:
sentencia sentencia ...
encabezado
Primera parte de una sentencia compuesta. Los encabezados empiezan con una palabra reservada y terminan con dos puntos.
cuerpo
Segunda parte de una sentencia compuesta. El cuerpo consiste de una secuencia de sentencias sangradas las misma distancia a partir del inicio del encabezado. El sangrado usual usado en la comunidad Python es de 4 espacios.
llamada a función
Una sentencia que ejecuta una función. Está compuesta por el nombre de la función más una lista de argumentos encerrados entre paréntesis.
flujo de ejecución
Orden en el que se ejecutan las sentencias durante la ejecución de un programa.
parámetro
Nombre que se usa dentro de una función para referirse al valor que se le pasa como argumento.
import

Sentencia que permite que las funciones y variables definidas en un guión de Python estén disponibles en el ámbito de otro guión o en una sesión interactiva con la terminal de Python.

Por ejemplo, suponga que las siguientes instrucciones están en un guión llamado pruebame.py:

def muestra_tres_veces(algo):
    print algo, algo, algo

    n = 42
    c = "Y ahora algo completamente diferente..."

Ahora inicie una sesión en la terminal de Python desde el mismo directorio donde se localiza pruebame.py:

$ ls
pruebame.py  &lt;y otras cosas...&gt;
$ python
>>>

Se han definido tres nombres en pruebame.py: muestra_tres_veces, n, y c. Si intentamos acceder a cualquiera de ellos desde la terminal, sin haberlos importado primero, obtenemos un error:

>>> n
Traceback (most recent call last):
  File <stdin>", line 1, in <module>
NameError: name 'n' is not defined
>>> muestra_tres_veces("¡ay!")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'muestra_tres_veces' is not defined

Sin embargo, si importamos todo el contenido de pruebame.py, podemos usar todo lo que ahí está definido:

>>> from pruebame import *
>>> n
42
>>> c
'Y ahora algo completamente diferente...'
>>> muestra_tres_veces("¡Hurra!")
¡Hurra! ¡Hurra! ¡Hurra!
>>>

Nótese que usted no incluyó la extensión .py del nombre del guión en la sentencia import.

argumento
Valor que se le pasa a una función cuando se la llama. El valor se asigna al parámetro correspondiente de la función.
composición de función
Uso de la salida de una llamada a función como la entrada de otra.
variable local
Variable definida dentro de una función. Las variables locales sólo pueden usarse dentro de su función.
diagrama de pila
Representación gráfica de una pila de funciones, sus variables y los valores a los que se refieren.
marco
Recuadro que en un diagrama de pila representa una llamada a función. Contiene las variables locales y los parámetros de la función.
trazado inverso
Listado de las funciones en curso de ejecución, presentadas cuando sucede un error en tiempo de ejecución. Es común que al trazado inverso también se le conozca como trazado de pila porque lista las funciones en el orden en el cual son almacenadas en la pila de llamadas.

3.8. Ejercicios

  1. Con un editor de texto cree un guión de Python que se llame pruebame3.py. Escriba en este archivo una función que se llame nueve_lineas que use la función tres_lineas para mostrar nueve líneas en blanco. Enseguida agregue una función que se llame limpia_pantalla que muestre veinticinco líneas en blanco. La última instrucción en su programa debe ser una llamada a limpia_pantalla.

  2. Mueva la última instrucción del archivo pruebame3.py al inicio del programa, de forma tal que la llamada a la función limpia_pantalla esté antes que la definición de función. Ejecute el programa y registre qué mensaje de error obtiene. ¿Puede establecer una regla sobre las definciones de funciones y las llamadas a función que describa la posición relativa entre ellas en el programa?

  3. Utilizando la versión que funciona de pruebame3.py mueva la definición de nueva_linea después de la definción de tres_líneas. Registre qué sucede cuando ejecuta el programa. Ahora mueva la definición de nueva_linea debajo de una llamada a tres_líneas(). Explique cómo es que éste es un ejemplo de la regla que estableció en el ejercicio previo.

  4. Cree el cuerpo de la definición de función de concatena_n_veces de forma tal que muestre la cadena c, n veces:

    def concantena_n_veces(c, n):
        "Cree su código aquí"
    

    Guarde este función en un guión llamado prueba_import.py. Ahora en el indicador de Unix asegúrese de que usted se encuentra en el mismo directorio donde se localiza el archivo prueba_import.py (el comando ls debe mostrar el archivo prueba_import.py). Inicie la terminal de Python y pruebe lo siguiente:

    >>> from prueba_import import *
    >>> concatena_n_veces('Basura', 7)
    BasuraBasuraBasuraBasuraBasuraBasuraBasura
    

    Si todo sale bien su sesión lucirá como esta. Experimente con otras llamadas a concatena_n_veces hasta que usted se sienta a gusto con los resultados obtenidos.