Cibernetia > Manuales > Python
Búsqueda personalizada







Capítulo 3: Funciones

3.1 Llamadas a funciones

En el contexto de la programación, una función es una secuencia de instrucciones, identificada mediante un nombre, que ejecuta un algoritmo. Al definir una función, se especifica el nombre y la secuencia de instrucciones. Una vez definida, se puede "recuperar" la función llamándola por su nombre. Ya hemos visto un ejemplo de una llamada a una función:

>>> type('32')

El nombre de la función es type. La expresión entre paréntesis se llama "argumento" de la función. El resultado para esta función es el tipo del argumento, que es, en este caso, una cadena.

Es habitual decir que una función "toma" un argumento y "devuelve" un resultado. El resultado se denomina "valor de retorno".

Cuando se llama a una función en el modo interactivo, el intérprete muestra el valor de retorno, pero en un script, en cambio, la llamada a una función no muestra nada. Para ver el resultado en la pantalla, hace falta una orden expresa:

print type('32')

O podemos asignar el valor de retorno a una variable, que se puede imprimir o se puede utilizar inmediatamente o más tarde con otros fines.

stereo = type('32')
print stereo

3.2 Funciones de conversión de tipos

Python proporciona funciones incorporadas que convierten los valores de un tipo a otro. La función int toma cualquier valor y lo convierte en un entero, si es posible, o "se queja" (es decir, lanza un mensaje de error) si no es posible:

>>> int('32')
32
>>> int('Hello')
ValueError: invalid literal for int(): Hello

int puede convertir los valores en coma flotante a enteros, pero no redondea, sino que, simplemente, extrae la parte entera del número:

>>> int (3.99999)
3
>>> int(-2,3)
-2

float convierte enteros y cadenas en números de coma flotante:

>>> float(32)
32,0
>>> float('3.14159 ')
3,14159

Por último, str convierte su argumento en una cadena de caracteres:

>>> str(32)
'32'
>>> str(3.14149)
'3.14149'

3.3 Funciones matemáticas

Python tiene un módulo de matemáticas que proporciona la mayor parte de las funciones matemáticas habituales. Un módulo es un archivo que contiene una colección de funciones relacionadas.

Antes de poder usar el módulo, tenemos que importarlo:

>>> import math

Esta declaración crea un objeto módulo llamado math. Si lanzamos la orden de imprimir el objeto, obtenemos cierta información sobre él:

>>> print math

El objeto módulo contiene las funciones y variables definidas en el módulo. Para acceder a una de las funciones, hay que especificar el nombre del módulo y el nombre de la función, separados por un punto. Este formato se denomina "notación punto" (dot notation).

>>> ratio = signal_power / noise_power
>>> decibels = 10 * math.log10(ratio)

>>> radians = 0.7
>>> height = math.sin(radians)

El primer ejemplo calcula el logaritmo en base 10 del ratio entre las variables. El módulo de matemáticas también ofrece una función llamada log que calcula la base de logaritmos e

El segundo ejemplo calcula el seno de la variable radians. El nombre de la variable nos da una pista sobre el hecho de que el seno y otras funciones trigonométricas (coseno, tangente, etc) se sirven de argumentos expresados en radianes. Para convertir de grados a radianes, hay que dividir por 360 y multiplicar por 2 π:

>>> degrees = 45
>>> radians = degrees / 360.0 * 2 * math.pi
>>> math.sin(radians)
0.707106781187

La expresión math.pi obtiene la variable pi del módulo de matemáticas. Convenientemente, el valor de esta variable es una aproximación de π precisa que contiene alrededor de 15 dígitos.

Si sabes de trigonometría, puedes comprobar el resultado anterior comparándolo con la raíz cuadrada de dos dividida entre dos:

>>> math.sqrt(2) / 2.0
0.707106781187

3.4 Composición

Hasta ahora, hemos examinado los elementos de un programa (variables, expresiones, declaraciones) de forma independiente, sin mencionar la posibilidad de combinar tales elementos.

Una de las características más útiles de los lenguajes de programación es su capacidad para partir de pequeños bloques de código y combinarlos para componer estructuras más complejas de código. Por ejemplo, el argumento de una función puede ser cualquier tipo de expresión, incluso operadores aritméticos:

x = math.sin (grados / 360,0 * 2 * math.pi)

E incluso llamadas a funciones:

x = math.exp (math.log (X +1))

Casi en cualquier lugar se puede introducir un valor o una expresión arbitraria, con una excepción: el lado izquierdo de una instrucción de asignación de valor debe ser siempre un nombre de variable. Introducir una expresión (y no un nombre de variable) en el lado izquierdo de una asignación constituye un error de sintaxis.

>>> minutes = hours * 60                 # right
>>> hours * 60 = minutes                 # wrong!
SyntaxError: can't assign to operator

3.5 Añadir nuevas funciones

Hasta ahora, sólo hemos estado usando las funciones que vienen "de serie" con Python, pero también es posible añadir nuevas funciones. La definición de una función especifica el nombre de una la función y la secuencia de instrucciones que se ejecutará cuando se llame a la función.

He aquí un ejemplo:

def print_lyrics():
    print "I'm a lumberjack, and I'm okay."
    print "I sleep all night and I work all day."

def es una palabra clave que indica que se trata de la definición de una función. El nombre de la función es print_lyrics. Las reglas para los nombres de las funciones son las mismas que para los nombres de variables: las letras, los números y algunas marcas de puntuación son legales, pero el primer carácter no puede ser nunca un número. No se puede utilizar una palabra clave como nombre de una función, y se debe evitar que existan una variable y una función con el mismo nombre.

El paréntesis vacío después del nombre de la función indica que ésta no recibe ningún argumento.

La primera línea de la definición de la función se llama "cabecera"; el resto se llama "cuerpo". La cabecera tiene que acabar forzosamente con dos puntos y el cuerpo debe estar sangrado. Por convenio, el sangrado es de cuatro espacios siempre. El cuerpo puede contener cualquier número de instrucciones.

Las cadenas en las instrucciones de impresión se deben escribir entre comillas. Las comillas simples y dobles hacer lo mismo. La mayoría de las personas utilizan comillas simples, salvo en aquellos casos en que una comilla simple (o un apóstrofe) aparece en la cadena.

Si se escribe la definición de una función en el modo interactivo, el intérprete imprime puntos suspensivos (...) para informar de que la definición no está completa:

>>> def print_lyrics():
...     print "I'm a lumberjack, and I'm okay."
...     print "I sleep all night and I work all day."
...

Para finalizar la función, se debe introducir una línea en blanco (esto no es necesario en un script; sólo en el modo interactivo de intérprete de órdenes).

La definición de una función crea una variable con el mismo nombre.

>>> print print_lyrics

>>> print type(print_lyrics)

El valor de print_lyrics es una objeto función, cuyo tipo es function.

La sintaxis para llamar a la nueva función es la misma que para las funciones nativas (aquéllas que vienen "de serie", sin necesidad de que el usuario las defina):

>>> print_lyrics()
I'm a lumberjack, and I'm okay.
I sleep all night and I work all day.

Una vez definida una función, se puede utilizar dentro de otra función. Por ejemplo, para repetir el estribillo anterior, podríamos escribir una función llamada repeat_lyrics:

def repeat_lyrics():
    print_lyrics()
    print_lyrics()

Y, una vez definida, llamar a repeat_lyrics:

>>> repeat_lyrics()
I'm a lumberjack, and I'm okay.
I sleep all night and I work all day.
I'm a lumberjack, and I'm okay.
I sleep all night and I work all day.

(Aunque en verdad la canción no sea así.)

3.6 Definiciones y usos

Aunando los fragmentos de código de la sección anterior, el programa en su conjunto se parece a esto:

def print_lyrics():
    print "I'm a lumberjack, and I'm okay."
    print "I sleep all night and I work all day."

def repeat_lyrics():
    print_lyrics()
    print_lyrics()

repeat_lyrics()

Este programa contiene dos definiciones de funciones: print_lyrics y repeat_lyrics. Las definiciones de funciones se ejecutan como cualquier otra instrucción, pero su efecto es la creación de una nueva función. Las instrucciones dentro de la función no se llegan a ejecutar hasta que se invoca la función; es decir, la definición de una función no genera ninguna salida.

Como cabría esperar, hay que crear una función antes de que ésta se pueda ejecutar. En otras palabras, la función se ha de definir antes de que ésta se invoque por primera vez.

Ejercicio 1. Mueve la última línea de este programa al principio, de forma que la llamada a la función se produzca antes de que se ejecuten las definiciones de las funciones. Ejecuta el programa modificado y comprueba el mensaje de error que aparecerá (o debería aparecer).

Ejercicio 2. Mueve de nuevo la última línea de este programa al final (es decir, déjalo como estaba antes de que lo estropeáramos) y mueve la definición de print_lyrics después de la definición de repeat_lyrics. ¿Qué pasa cuando se ejecuta el programa?

3.7 Flujo de ejecución

Con el fin de garantizar que las funciones se han definido antes de su primer uso, hay que conocer el orden en que se ejecutan las instrucciones, es decir, el flujo de ejecución.

La ejecución siempre comienza en la primera declaración del programa. Las declaraciones se realizan de una en una, de arriba abajo.

Las definiciones de funciones no alteran el flujo de ejecución del programa, pero recuerda que las declaraciones dentro de la función no se ejecutan hasta que se invoca la función.

Una llamada a la función es como un desvío en el flujo de ejecución. En lugar de ir a la siguiente instrucción, el flujo salta al cuerpo de la función, ejecuta sus instrucciones, y luego regresa al punto donde se interrumpió la ejecución.

Eso parece bastante simple, pero hay que recordar que una función puede llamar a otras, lo cual dificulta progresivamente el seguimiento del flujo de ejecución. En medio de una función, el programa podría tener que ejecutar las instrucciones de otra función. Y mientras se ejecuta la nueva función, el programa podría tener que empezar a ejecutar otra función más.

Afortunadamente, Python es experto en seguir la pista del flujo de ejecución, por lo que cada vez que completa la ejecución de una función, el programa continúa allí donde llamó a la función cuya ejecución ha acabado. Cuando llega a la final del programa, acaba.

¿Cuál es la moraleja de esta sórdida historia? Recuerda que leer un programa no siempre implica leerlo de arriba abajo. A veces es más razonable seguir la pista al flujo de ejecución.

3.8 Parámetros y argumentos

Algunas de las funciones nativas (incorporadas) necesitan argumentos. Por ejemplo, si llamas a math.sin debes pasar un número (en radianes) como argumento. Algunas funciones tiene más de un argumento; math.pow toma dos, la base y el exponente.

Dentro de la función, las variables que reciben el valor de los argumentos se llaman parámetros. Aquí hay un ejemplo de una función definida por el usuario que toma un argumento:

def print_twice(bruce):
    print bruce
    print bruce

Esta función asigna el argumento a un parámetro llamado bruce. Cuando se llama a la función, se imprime dos veces el valor del parámetro, sea cual sea.

Esta función trabaja con cualquier valor que se puede imprimir.

>>> print_twice('Spam')
Spam
Spam
>>> print_twice(17)
17
17
>>> print_twice(math.pi)
3.14159265359
3.14159265359

Las normas de composición que se aplican a las funciones nativas también se aplican a funciones definidas por el usuario, de manera que podemos utilizar cualquier tipo de expresión como argumento para print_twice:

>>> print_twice('Spam '*4)
Spam Spam Spam Spam
Spam Spam Spam Spam
>>> print_twice(math.cos(math.pi))
-1.0
-1.0

El argumento es evaluado antes de llamar a la función, por lo que, en los ejemplos, las expresiones 'Spam '* 4 y math.cos(math.pi) se evalúan sólo una vez. También puedes usar una variable como argumento:

>>> michael = 'Eric, the half a bee.'
>>> print_twice(michael)
Eric, the half a bee.
Eric, the half a bee.

El nombre de la variable se pasa como argumento (michael) no tiene nada que ver con el nombre del parámetro (bruce). No importa con qué nombre pasemos el valor; dentro de print_twice, llamamos a todo bruce.

3.9 Las variables y los parámetros son locales

Al crear una variable dentro de una función, dicha variable es local, lo que significa que sólo existe dentro de la función. Por ejemplo:

def cat_and_print_twice(part1, part2):
    cat = part1 + part2
    print_twice(cat)

Esta función tiene dos argumentos: los concatena e imprime el resultado dos veces. Aquí hay un ejemplo de su uso:

>>> line1 = 'Bing tiddle '
>>> line2 = 'tiddle bang.'
>>> cat_and_print_twice(line1, line2)
Bing tiddle tiddle bang.

Bing tiddle tiddle bang.

Cuando cat_and_print_twice termina, la variable cat es destruida. Si tratamos de imprimirla, obtenemos una excepción:

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

Los parámetros son también locales. Por ejemplo, fuera de print_twice, no existe bruce.

3.10 Stack diagramas

Para realizar un seguimiento de dónde puede ser utilizada cada variable, puede ser útil dibujar un diagrama de pila. Al igual que el diagrama de estado, el diagramas de pila muestra el valor de cada variable, y muestra además la función a que pertenece cada variable.

Cada función se representa mediante un marco. Un marco es una caja con el nombre de la función junto a él y con los nombres de los parámetros y variables de la función dentro de ella. El diagrama de pila para el ejemplo anterior sería este:

Los marcos están dispuestos en una pila que indica qué función llamó a cuál, y así sucesivamente. En este ejemplo, print_twice fue llamada por cat_twice, y cat_twice fue llamada por __main__, que es un nombre especial para el marco máximo. Cuando creas una variable fuera de cualquier función, ésta pertenece a __main__.

Cada parámetro se refiere al mismo valor que su correspondiente argumento. Así, part1 tiene el mismo valor que la line1, part2 tiene el mismo valor que line2, y bruce tiene el mismo valor que el cat.

Si se produce un error durante una llamada a una función, Python imprime el nombre de la función, y el nombre de la función que llamó a la primera, y el nombre de la función que llamó a la anterior, y así sucesivamente hasta llegar a la función __main__.

Por ejemplo, si se intenta acceder a cat dentro de print_twice, obtendrás un NameError:

Traceback (innermost last):
  File "test.py", line 13, in __main__
    cat_and_print_twice(line1, line2)
  File "test.py", line 5, in cat_and_print_twice
    print_twice(cat)
  File "test.py", line 9, in print_twice
    print cat
NameError: name 'cat' is not defined

Esta lista de funciones se llama traceback (algo así como "rastro"). Nos informa sobre el archivo de programa en que ocurrió el error, en qué línea se produjo y qué funciones se ejecutaban en ese momento. También muestra la línea de código que causó el error.

El orden de las funciones en el traceback es el mismo que en el de los marcos del diagrama de pila. La función que se está ejecutando se encuentra en la parte inferior.

3.11 Funciones no nulas y funciones nulas

Algunas de las funciones que estamos usando, como la funciones matemáticas, devuelven un valor; a falta de un nombre mejor, las llamaremos funciones no nulas. Otras funciones, como print_twice, realizan una acción pero no devuelven ningún valor. Se llaman funciones nulas.

Cuando llamas a una función no nula querrás, normalmente, hacer algo con el resultado, como, por ejemplo, asignarlo a una variable o utilizarlo como parte de una expresión:

x = math.cos(radians)
golden = (math.sqrt(5) + 1) / 2

Cuando llamas a una función en el modo interactivo, Python muestra el resultado:

>>> math.sqrt(5)
2.23606797749978
98

Pero en un script, si se llama a una función no nula y no se hace nada con el resultado, éste se pierde.

math.sqrt(5)

Este script calcula la raíz cuadrada de 5, pero al no mostrar ni almacenar el resultado, no es muy útil.

Las funciones nulas pueden mostrar algo en la pantalla o tener algún otro efecto, pero no tienen un valor de retorno. Si intentas asignar el resultado a una variable, se obtiene un valor especial llamado None.

>>> result = print_twice('Bing')
Bing
Bing
>>> print result
None
El valor None no es lo mismo que la cadena 'None'. Es un valor especial con un tipo propio:
>>> print type(None)
>

Las funciones que hemos escrito hasta ahora son todas nulas. Vamos a comenzar a escribir funciones no nulas en unos pocos capítulos.

3.12 ¿Por qué funciones?

Puede que no esté claro por qué vale la pena molestarse en dividir un programa en funciones. Hay un montón de razones. He aquí algunas:

  • La creación de una nueva función te da la oportunidad de poner nombre a un grupo de estados, lo que hace que tu programa sea más fácil de leer y depurar.
  • Las funciones pueden reducir el tamaño de un programa mediante la eliminación de código repetitivo. Más tarde, si introducimos algún cambio, sólo habrá que hacerlo en un único lugar.
  • La división de un programa largo en funciones te permite depurar las piezas por partes y posteriormente juntarlas para que trabajen conjuntamente.
  • Las funciones bien diseñadas pueden servir para muchos programas para muchos programas. Una vez escritas y depuradas, son reutilizables.

    3.13 Depuración

    Si estás usando un editor de texto para escribir tus scripts, es posible que tengas problemas con los espacios y las tabulaciones. La mejor manera de evitar estos problemas es utilizar espacios exclusivamente, sin tabulaciones. La mayoría de editores de texto preparados para Python hacen esto mismo por defecto, pero otros no lo hacen.

    Normalmente los tabuladores y los espacios son invisibles, lo cual los hace difíciles de depurar, por lo que hay que tratar de encontrar un editor que sangre el texto correctamente.

    No olvides guardar tus programas antes de ejecutarlos. Algunos entornos de desarrollo hacen esto automáticamente, pero otros no. Si no guardas antes de ejecutar, el código que estás viendo en el editor no será el código que ejecute el intérprete de Python.

    La depuración puede llevar mucho tiempo si ejecutas una y otra vez el mismo código incorrecto. Y esto me lleva al Tercer Teorema de la Depuración:

    Asegúrate de que el código que estás viendo en la pantalla es el código que se está ejecutando.

    Si no estás seguro, pon algo así como print "¡hola!" al principio del programa y ejecútalo de nuevo. Si no ves '¡hola!' quiere decir que no estás ejecutando el programa.

    3.14 Glosario

    • Función: una secuencia de declaraciones que realiza alguna operación útil, a la cual se ha asignado un nombre. Las funciones pueden tener o no argumentos y pueden producir o no un resultado.
    • Definición de la función: una declaración que crea una nueva función, indicando su nombre, los parámetros y las instrucciones que hay que ejecutar cuando se llame a la función.
    • Objeto función: un valor creado por la definición de la función. El nombre de la función es una variable que se refiere a una objeto función.
    • Cabecera: la primera línea de la definición de una función.
    • Cuerpo: la secuencia de declaraciones dentro de la definición de una función.
    • Parámetro: un nombre que se utiliza dentro de una función para referirse al valor pasado como argumento.
    • Llamada a una función: una declaración fuerza la ejecución de una función. Consiste en el nombre de la función seguido de una lista de argumentos.
    • Argumento: valor que pasamos a la función cuando la llamamos. Este valor es asignado a su correspondiente parámetro en la función.
    • Variable local: una variable definida dentro de una función. Una variable local sólo puede usarse dentro de su función.
    • Valor de retorno: el resultado de una función. Si utilizamos como expresión una llamada a una función, el valor de retorno es el valor de la expresión.
    • Función no nula: una función que devuelve un valor.
    • Función nula: una función que no devuelve ningún valor.
    • Módulo: una secuencia de declaraciones y definiciones de funciones almacenadas en un archivo.
    • Declaración de importación: una declaración que lee un archivo módulo y crea un objeto módulo.
    • Objeto módulo: un valor creado por una declaración de importación que proporciona acceso a los valores definidos en el módulo.
    • Notación punto: la sintaxis para la declaración de una función en otro módulo, indicando el nombre del módulo seguido de un punto y el nombre de la función.
    • Composición: la capacidad para combinar las expresiones y declaraciones simples para formar expresiones y declaraciones compuestas.
    • Flujo de ejecución: el orden en que se ejecutan las declaraciones durante la ejecución del programa.
    • Diagrama de pila: una representación gráfica de una pila de funciones, sus variables, y los valores a que se refieren.
    • Marco: un cuadro en un diagrama de pila, que representa una llamada a una función. Contiene las variables locales y los parámetros de la función.
    • Traceback: una lista impresa de las funciones que se están ejecutando cuando se produce una excepción.
Manuales | Tesis: Ordenadores, Circuitos integrados...
english
Cibernetia