![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Ya hemos visto un ejemplo de una llamada a función:
>>> type("32")
<type 'string'>
El nombre de la función es type, y visualiza el tipo de un valor o variable. El valor o variable, denominado argumento de la función, tiene que ir entre paréntesis. Es muy común decir que una función "toma" un argumento y "devuelve" un resultado. A este resultado se le llama valor de retorno.
En lugar de imprimir el valor de retorno, le podemos asignar una variable:
>>> betty = type("32")
>>> print betty
<type 'string'>
A modo de otro ejemplo, la función id toma un valor o una variable y devuelve un número entero que hace de identificador único para ese valor:
>>> id(3)
134882108
>>> betty = 3
>>> id(betty)
134882108
Cada valor tiene un id, que es un número único relacionado con el lugar donde está almacenado en la memoria del ordenador. El id de una variable es el id del valor al que se refiere.
Comentarios
Python proporciona un conjunto de funciones incorporadas que convierten valores de un tipo a otro. La función int toma un valor y lo convierte en un número entero, si es posible, o si no, se queja:
>>> int("32")
32
>>> int("Hola")
ValueError: invalid literal for int(): Hola
int también puede convertir valores decimales en números enteros, pero recuerda que eso trunca la parte fraccionaria. También debes tener en cuenta que Python está escrito en inglés, por lo que los valores de coma flotante están expresados mediante un punto, y no mediante coma, como sucede en español:
>>> int(3.99999)
3
>>> int(-2.3)
-2
La función float convierte números enteros y cadenas en números decimales:
>>> float(32)
32.0
>>> float("3.14159")
3.14159
Finalmente, la función str convierte al tipo cadena:
>>> str(32)
'32'
>>> str(3.14149)
'3.14149'
Puede parecer raro que Python distinga el valor del número entero 1 del valor de coma flotante 1,0. Ambos representan el mismo número, pero pertenecen a tipos diferentes. El motivo es que están representados de forma diferente dentro del ordenador.
Comentarios
Ahora que podemos convertir entre tipos, tenemos otra manera de ocuparnos de la división de números enteros. Retomando el ejemplo del capítulo anterior, supongamos que queremos calcular la fracción de una hora que ya ha transcurrido. La expresión más obvia, minuto / 60, pertenece a la aritmética de enteros, así que el resultado siempre es 0, incluso a 59 minutos pasados de la hora.
Una solución es convertir minuto en decimal y hacer una división de decimales:
>>> minuto = 59
>>> float(minuto) / 60.0
0.983333333333
Alternativamente podemos aprovecharnos de las reglas para la conversión automática de tipo, denominada coerción de tipo. Para los operadores matemáticos, si cualquier operando es del tipo float, el otro se convierte automáticamente del tipo float.
>>> minuto = 59
>>> minuto / 60.0
0.983333333333
Convirtiendo el denominador en decimal, obligamos a Python a hacer división de enteros.
Comentarios
En matemáticas habrás visto probablemente funciones como sin y log, y habrás aprendido a evaluar expresiones como sin(pi/2) y log(1/x). Primero, evalúas la expresión que está entre paréntesis (el argumento). Por ejemplo, pi/2 es aproximadamente 1,571, y 1/x es 0,1 (si x fuera 10,0).
Después evalúas la función en sí, ya sea mirándola en una tabla o realizando algunos cómputos. La sin de 1,571 es 1, y el log de 0,1 es -1 (suponiendo que log indique la base logarítmica 10).
Este proceso se puede aplicar repetidamente para evaluar expresiones más complicadas como log(1/sin(pi/2)). Primero, evalúas el argumento de la función más interna, luego evalúas la función y así sucesivamente.
Python cuenta con un módulo matemático que proporciona la mayoría de las funciones matemáticas familiares. Un módulo es un archivo que contiene un conjunto de funciones relacionadas agrupadas.
Antes de poder usar las funciones de un módulo tenemos que importarlas:
>>> import math
Para llamar a una de las funciones, tenemos que especificar el nombre del módulo y el nombre de la función, separados por un punto, también conocido como período. Este formato se denomina notación de punto.
>>> decibelio = math.log10 (17.0)
>>> ángulo = 1.5
>>> altura = math.sin(ángulo)
La primera instrucción le asigna decibelio al logaritmo de 17, base 10. También hay una función denominada log que toma el logaritmo de base e.
La tercera instrucción halla el seno del valor de la variable ángulo. sin y las otras funciones trigonométricas (cos, tan, etc.) toman argumentos en radianes. Para hacer la conversión de grados a radianes, divide entre 360 y multiplica por 2*pi. Por ejemplo, para hallar el seno de 45 grados, primero calcula el ángulo en radianes y luego obtén el seno:
>>> grados = 45
>>> ángulo = grados * 2 * math.pi / 360.0
>>> math.sin(ángulo)
La constante pi también forma parte del módulo matemático. Si sabes de geometría, puedes comprobar el resultado comparándolo con la raíz cuadrada de dos dividido entre dos:
>>> math.sqrt(2) / 2.0
0.707106781187
Al igual que con las funciones matemáticas, las funciones de Python pueden ser compuestas, en el sentido de que puedes usar una expresión como parte de otra. Por ejemplo, puedes usar cualquier expresión como un argumento de una función:
>>> x = math.cos(ángulo + math.pi/2)
Esta instrucción toma el valor de pi, lo divide entre 2 y añade el resultado al valor de ángulo. La suma constituye posteriormente un argumento de la función cos.
También puedes tomar el resultado de una función y convertirlo en un argumento de otra:
>>> x = math.exp(math.log(10,0))
Esta instrucción halla la base logarítmica e de 10 y luego eleva e a esa potencia. El resultado queda asignado a x.
Comentarios
Hasta ahora, sólo hemos estado usando las funciones que vienen con Python, pero también es posible añadir nuevas funciones. Crear nuevas funciones para resolver tus problemas particulares es uno de los aspectos más útiles de este lenguaje de programación con fines generales.
En el contexto de la programación, una función es una secuencia de instrucciones que lleva a cabo una determinada operación. Esta operación se especifica en una definición de función. Las funciones que hemos estado usando hasta ahora han sido definidas para nosotros, y se han ocultado estas funciones. Esto está bien, puesto que nos permite usar las funciones sin preocuparnos por los detalles de sus definiciones.
La sintaxis de una definición de función es:
def NOMBRE(LISTA DE PARÁMETROS):
INSTRUCCIONES
Puedes inventarte cualquier nombre para las funciones que crees, pero no puedes usar un nombre que sea una palabra clave de Python. La lista de parámetros especifica qué información tienes que proporcionar, si se da el caso, para usar la nueva función.
Puede haber un número cualquiera de instrucciones en la función, pero tienen que estar sangradas desde el margen izquierdo. En los ejemplos que aparecen en este libro, usaremos una sangría de dos espacios.
La primera pareja de funciones que vamos a escribir no tiene parámetros, por lo que la sintaxis se muestra así:
def nuevaLinea():
print
Esta función se llama nuevaLinea. Los paréntesis vacíos indican que no tiene parámetros. Sólo contiene una única instrucción, que da lugar a un cambio de renglón. (Esto es lo que ocurre cuando usas un comando print sin ningún argumento).
La sintaxis para llamar la nueva función es la misma que para funciones incorporadas:
print "Primera Línea."
nuevaLinea()
print "Segunda Línea."
El resultado de este programa es:
Primera Línea.
Segunda Línea.
Observa el espacio extra entre las dos líneas. ¿Y si quisiéramos más espacio entre las líneas? Podríamos llamar a la misma función repetidamente:
print "Primera Línea."
nuevaLinea()
nuevaLinea()
nuevaLinea()
print "Segunda Línea."
O podríamos escribir una nueva función llamada tresLineas que imprime tres líneas nuevas:
def tresLineas():
nuevaLinea()
nuevaLinea()
nuevaLinea()
print "Primera Línea."
tresLineas()
print "Segunda Línea."
Esta función contiene tres instrucciones, todas ellas sangradas con dos espacios. Dado que la siguiente instrucción no está sangrada, Python sabe que no es parte de la función.
Deberías fijarte en algunos aspectos de este programa:
Hasta ahora, quizás no esté claro por qué vale la pena crear todas estas funciones. En realidad, hay muchas razones, pero este ejemplo demuestra dos de ellas:
Como ejercicio, escribe una función llamada nueveLineas que utilice tresLineas para imprimir nueve espacios en blanco. ¿Cómo imprimirías veintisiete líneas nuevas?
Si unimos los fragmentos de código de la Sección 3.6, el programa entero aparecerá así: a
def tresLineas():
print
def tresLineas():
nuevaLinea()
nuevaLinea()
nuevaLinea()
print "Primera Línea."
tresLineas()
print "Segunda Línea."
Este programa contiene dos definiciones de función: nuevaLinea y tresLineas. Las definiciones de funciones se ejecutan exactamente igual que otras instrucciones, pero en este caso se crea una función nueva. Las instrucciones que están dentro de la función no son ejecutadas hasta que se llama a la función, y la definición de función no genera ningún resultado.
Como es de esperar, tienes que crear una función antes de poder ejecutarla. En otras palabras, la definición de funciones tiene que ser ejecutada antes de ser llamada por primera vez.
Como ejercicio, traslada las tres últimas líneas de este programa a la parte superior, de modo que las llamadas de función aparezcan antes que las definiciones. Ejecuta el programa y mira qué mensaje de error te aparece.
Otro ejercicio: comienza con la versión momentánea del programa y traslada la definición de nuevaLinea después de la definición de tresLineas. ¿Qué ocurre cuando ejecutas el programa?
Para asegurar que una función es definida antes de su primer uso, tienes que saber el orden en el que se ejecutan las instrucciones, lo que recibe el nombre de flujo de ejecución.
La ejecución siempre empieza en la primera instrucción del programa. Las instrucciones se ejecutan de una en una, empezando de arriba hacia abajo.
Las definiciones de funciones no alteran el flujo de ejecución del programa, pero recuerda que las instrucciones que están dentro de la función no son ejecutadas hasta que se llama a la función. Aunque no es lo común, puedes definir una función dentro de otra. En este caso, la definición interna no se ejecuta hasta que se llama la función externa.
Las llamadas de funciones son como un desvío en el flujo de ejecución. En vez de pasar a la siguiente instrucción, el flujo salta a la primera línea de la función llamada, ejecuta todas las instrucciones allí, y entonces regresa para continuar donde lo había dejado.
Esto parece bastante simple, hasta que recuerdas que una función puede llamar a otra. Incluso si se encuentra a mitad de una función, puede que el programa tenga que ejecutar las instrucciones de otra función. Pero mientras ejecuta esa nueva función, ¡puede que el programa todavía tenga que ejecutar otra!
Afortunadamente, Python es experto en controlar dónde se encuentra, de manera que cada vez que se completa una función, el programa vuelve donde lo había dejado en la función que la había llamado. Cuando llega al final del programa, finaliza.
¿Cuál es la moraleja de este sórdido cuento? Cuando leas un programa, no lo hagas de arriba hacia abajo. En vez de eso, sigue el flujo de ejecución.
Comentarios
Algunas de las funciones incorporadas que has usado requieren argumentos, los valores que controlan cómo tiene que hacer su trabajo la función. Por ejemplo, si deseas encontrar el seno de un número, tienes que indicar de qué número se trata. Por esta razón, sin toma un valor numérico como un argumento.
Algunas funciones toman más de un argumento. Por ejemplo, pow toma dos argumentos, la base y el exponente. Dentro de la función, los diferentes valores se asignan a variables llamadas parámetros.
A continuación, un ejemplo de una función definida por el usuario que toma un parámetro:
def Doble(cruce):
print cruce, cruce
Esta función toma un solo argumento y lo asigna a un parámetro llamado cruce. El valor del parámetro (en este punto no tenemos ni idea de cuál será) se escribe dos veces, seguido de un nuevo renglón. El nombre cruce se eligió para mostrar que el nombre que le des al parámetro depende de ti, pero en general, querrás elegir algo más ilustrativo que cruce.
La función Doble sirve para cualquier tipo de valor:
>>> Doble('Spam')
Spam Spam
>>> Doble(5)
5 5
>>> Doble(3,14159)
3,14159 3,14159
En la primera llamada de función, el argumento es una cadena. En la segunda, es un número entero. En la tercera, es un float.
Las mismas reglas de composición que se aplican a las funciones incorporadas se aplican también a las funciones definidas por el usuario, de manera que podemos usar cualquier tipo de expresión como argumento de Doble:
>>> Doble('Spam'*4)
SpamSpamSpamSpam SpamSpamSpamSpam
>>> Doble(math.cos(math.pi))
-1,0 -1,0
Como de costumbre, la expresión es evaluada antes de que se ejecute el programa, de manera que Doble devuelve SpamSpamSpamSpam SpamSpamSpamSpam en vez de 'Spam'*4 'Spam'*4.
Como ejercicio, escribe una llamada a Doble que devuelva 'Spam'*4 'Spam'*4. Sugerencia: Las cadenas pueden encerrarse tanto entre comillas simples como dobles, y el tipo de comilla que no usemos para encerrar la cadena puede ser utilizada dentro de ella.
También podemos usar una variable como argumento:
>>> miguel = 'Elsa tiene una casa'.
>>> Doble(miguel)
Elsa tiene una casa. >>> miguel = 'Elsa tiene una casa'.
Aquí, ten en cuenta algo muy importante. El nombre de la variable que pasamos como un argumento (miguel) no tiene nada que ver con el nombre del parámetro (jose). No importa cómo se llamó al valor en el punto inicial; aquí en Doble, llamamos a todos jose. , Comentarios
Cuando creas una variable local dentro de una función, sólo existe dentro de la función, y no puedes usarla fuera. Por ejemplo:
def dosDoble(parte1, parte2):
dos = parte1 + parte2
doble(dos)
Esta función coge dos argumentos, los concatena, y luego imprime el resultado dos veces. Podemos llamar a la función con dos cadenas:
>>> chant1 = "Pie Jesu domine, "
>>> chant2 = "Dona eis requiem."
>>> dosDoble(chant1, chant2)
Pie Jesu domine, Dona eis requiem. Pie Jesu domine, Dona eis requiem.
Cuando dosDoble termina, la variable dos se destruye. Si intentamos imprimirla, obtenemos un error:
>>> print dos
NameError: dos
Los parámetros también son locales. Por ejemplo, fuera de la función Doble, no hay nada como jose. Si intentas usarlo, Python se quejará. Comentarios
Para distinguir qué variables se pueden usar y en qué lugar, normalmente es muy útil dibujar un diagrama de pila. Al igual que los diagramas de estado, los diagramas de pila no sólo muestran el valor de cada variable, sino que además muestran la función a la cual pertenece cada variable.
Cada función viene representada por un ciclo de operaciones. Un ciclo de operaciones es una casilla con el nombre de cada función al lado y los parámetros y variables de la función en su interior. El diagrama de pila del ejemplo anterior sería el siguiente:

El orden de la pila muestra el flujo de ejecución. Doble es llamada por dosDoble, y dosDoble llamada por __main__, que es un nombre especial para la función superior. Al crear una variable fuera de cualquier función, ésta pertenece a __main__.
Cada parámetro se refiere al mismo valor, así como su correspondiente argumento. Por tanto, parte1 tiene el mismo valor que chant1, parte2 tiene el mismo valor que chant2 y jose tiene el mismo valor que dos.
En caso de que haya un error durante una llamada a función, Python imprime el nombre de la función que la llamaba, y el nombre de la función que llamaba a aquella remite a __main__.
Por ejemplo, si intentamos acceder a dos desde Doble, obtendremos un NameError:
Traceback (innermost last):
File "test.py", line 13, in __main__
dosDoble(chant1, chant2)
File "test.py", line 5, in dosDoble
Doble(dos)
File "test.py", line 9, in Doble
print dos
NameError: dos
Esta lista de funciones se denomina traceback y te dice en qué archivo de programa tuvo lugar el error y en qué línea, así como qué funciones se estaban ejecutando al mismo tiempo. También muestra la línea de código que produjo el error.
Véase la semejanza entre el traceback y el diagrama de pila. No es ninguna coincidencia.
Comentarios
Seguro que ya te habías dado cuenta de que se obtienen resultados de algunas de las funciones que estamos usando, como las matemáticas. Otras funciones, como nuevaLinea, ejecutan una acción pero no devuelven un valor. De ahí se derivan algunas preguntas:
La respuesta a la tercera pregunta es sí, y lo veremos en el Capítulo 5.
A modo de ejercicio, responde a las otras dos preguntas poniéndolas en práctica. Cuando tengas una pregunta sobre lo que se puede hacer y lo que no en Pyhon, una buena manera de descubrirlo es preguntando al intérprete.Comentarios
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |