Herramientas Informaticas

Categoría: Sin categoría Página 33 de 51

3.5. Composición

Igual que con las funciones matemáticas, las funciones de Python se pueden componer; eso quiere decir que se usa una expresión como parte de otra. Por ejemplo, puede usar cualquier expresión como argumento de una función:

   1: x = math.cos(angulo + pi/2)

Esta sentencia toma el valor de pi, lo divide entre dos y le añade el resultado al valor de angulo. La suma se pasa luego como argumento a la funcion cos.

También puede tomar el resultado de una funcion y pasarselo como argumento a otra:

   1: x = math.exp(math.log(10.0))

Esta sentencia encuentra el logaritmo en base e de 10 y luego eleva e a ese exponente. El resultado queda asignado a x.

3.6. Añadir funciones nuevas

Hasta ahora solo hemos usado las funciones que vienen incluidas con Python, pero también es posible añadir nuevas funciones. La creación de nuevas funciones para resolver sus problemas particulares es una de las cosas mas útiles de los lenguajes de programación de propósito general.

En contextos de programación, función es una secuencia de instrucciones con nombre, que lleva a cabo la operación deseada. Esta operación se especifica en una definición de función. Las funciones que hemos usado hasta ahora las han definido por nosotros, y esas definiciones están ocultas. Eso es bueno, ya que nos permite usar funciones sin preocuparnos sobre los detalles de sus definiciones.

La sintaxis de la definición de una función es:

   1: def NOMBRE( LISTA DE PARAMETROS ):

   2:     SENTENCIAS

Puede inventarse el nombre que desee para su funcion, con la excepcion de que no puede usar las palabras reservadas de Python. La lista de parámetros especifica que informacion, en caso de haberla, ha de proporcionar para usar la función nueva.

Puede haber cualquier numero de sentencias dentro de la funcion, pero tienen que estar indentadas desde el margen izquierdo. En los ejemplos de este libro se usara una indentacion de dos espacios.

El primer par de funciones que escribiremos no tienen parametros, de manera que su sintaxis es:

   1: def nueva_linea():

   2:     print

Esta funcion se llama nueva linea. Los parentesis vac³os indican que no tiene parámetros. Contiene una unica sentencia, que muestra como salida un carácter de nueva línea (es lo que sucede cuando utiliza una orden print sin argumentos).

Llamamos entonces a la funcion nueva usando la misma sintaxis que usamos para las funciones internas:

   1: print "Primera linea."

   2: nueva_linea()

   3: print "Segunda linea."

   4: The output 

   5: of this program is

   6: Primera linea.

   7: Segunda linea.

Observe el espacio a~nadido que hay entre las dos l³neas. Si quisieramos mas espacios, entre las l³neas, >que har³amos? Podemos llamar varias veces a la misma función:

   1: print "Primera 

   2: linea."

   3: nueva_linea()

   4: nueva_linea()

   5: nueva_linea()

   6: print "Segunda 

   7: linea."

O bien podemos escribir una nueva funcion que llamaremos tresLineas, y que imprima tres nuevas líneas:

   1: def tresLineas():

   2:     nueva_linea()

   3:     nueva_linea()

   4:     nueva_linea()

   5:     print 

   6:     "Primera Linea."

   7:     tresLineas()

   8:     print "Segunda Linea."

   9:     

Esta funcion contiene tres sentencias, las cuales estan todas indentadas con dos espacios. Puesto que la siguiente sentencia no esta indentada, Python sabe que no es parte de la funcion.

Observe los siguientes puntos con respecto a este programa:

1. Se puede llamar al mismo procedimiento repetidamente. De hecho es bastante util hacerlo, ademas de habitual.
2. Se puede llamar a una funcion desde dentro de otra funcion: en este caso tresLineas llama a nueva linea.

Hasta ahora puede no haber quedar claro por que vale la pena crear todas estas funciones nuevas. En realidad hay much³simas razones, pero este ejemplo demuestra dos:

Crear una nueva funcion le da la oportunidad de dar un nombre a un grupo de sentencias. Las funciones simplifican su programa al ocultar cálculos complejos detras de ordenes sencillas, y usar palabras de su propia lengua
en vez de codigo arcano.

Crear una nueva funcion hace que el programa sea mas pequeño, al eliminar codigo repetitivo. Por ejemplo, una manera de imprimir nueve líneas consecutivas es llamar a tresLineas tres veces.

Como actividad, escriba una funcion llamada nueveLineas que use tresLineas para imprimir nueve líneas en blanco. ¿Como imprimiría 27 líneas nuevas?

3.7. Las definiciones y el uso

Juntando los fragmentos de código de la sección anterior, el programa completo queda de la siguiente manera:

   1: def nueva_linea():

   2:     print

   3: def 

   4:     tresLineas():

   5:     nueva_linea()

   6:     nueva_linea()

   7:     nueva_linea()

   8:     print 

   9:     "Primera Linea."

  10:     tresLineas()

  11:     print "Segunda Linea."

El presente programa contiene dos definiciones de funciones: nueva linea y tresLineas. Las de¯niciones de funciones se ejecutan como el resto de sentencias, pero el efecto es crear una nueva funcion. Las sentencias del interior de la funcion no se ejecutan hasta que se llama a la funcion, y la definición de la función no genera salida.

Como era de esperar, tiene que crear una funcion antes de poder ejecutarla.

En otras palabras, la definición de la funcion tiene que ejecutarse antes de la primera vez que se la invoque.

Como actividad, pruebe a ejecutar este programa moviendo las tres ultimas sentencias al principio del programa. Registre que mensaje de error obtiene usted.

Como segunda actividad, pruebe a tomar la version del programa que funcionaba y a mover la definición de nueva linea mas abajo que la definición de tresLineas .

¿Que ocurre cuando ejecuta el programa?

3.8. Flujo de ejecución

Para asegurarse de que una función se define antes de su primer uso, tiene que conocer el orden en el que se ejecutan las sentencias; a esto se le llama flujo de ejecución.

La ejecución comienza siempre por la primera sentencia del programa. Las sentencias se ejecutan a razón de una cada vez, en orden, hasta que se alcanza una llamada a una función.

Las definiciones de funciones no alteran el flujo de ejecución del programa, pero recuerde que las sentencias que hay dentro de la función no se ejecutan hasta que se hace la llamada a la función. Aunque no es habitual, puede definir una función dentro de otra. En este caso, la definición de función interior no se ejecuta hasta que no se llama a la función exterior.

Las llamadas a funciones son como un desvío en el flujo de ejecución. En lugar de ir a la siguiente sentencia, el flujo salta hasta la primera línea de la función a la que se llama, ejecuta todas las sentencias que encuentre allí, y vuelve a
retomar la ejecución en el punto donde lo dejo.

Esto suena bastante sencillo… hasta que se acuerda de que una función puede llamar a otra. Mientras estamos en medio de una función, podríamos vernos obligados a abandonarla e ir a ejecutar sentencias en otra función mas. Pero mientras estamos en esta nueva función, ¡podríamos salirnos y ejecutar otra función mas!

Afortunadamente, a Python se le da bien tomar nota de donde esta, de manera que cada vez que se completa una función, el programa retoma el punto en donde lo dejo en la función que hizo la llamada. Cuando llega al final del programa, termina.

¿Cual es la moraleja de toda esta historia?

Cuando este leyendo un programa, no lo lea desde la parte superior a la inferior. En lugar de eso, siga el flujo de ejecución.

3.9. Parámetros y argumentos

Algunas de las funciones internas que hemos usado precisan de argumentos, los valores que controlan como la función lleva a cabo su tarea.

Por ejemplo, si desea encontrar el seno de un numero, tiene que indicar de que numero se trata. Así pues, sin toma como argumento un valor numérico.

Algunas funciones toman mas de un argumento, como pow, que toma dos argumentos: la base y el exponente. Dentro de la función, los valores que se le han pasado se asignan a variables llamadas parámetros.

He aquí un ejemplo de una función definida por el usuario, que toma un parámetro:

   1: def imprimeDoble(paso):

   2: print paso, paso

Esta funcion toma un unico argumento y se lo asigna a un parametro llamado paso. El valor del parametro (en este punto todavía no tenemos ni idea de cual será) se imprime dos veces, seguido por un caracter de nueva línea. El nombre paso se eligio para sugerir que el nombre que le de a un parametro depende de usted, pero en general es mejor que elija un nombre mas ilustrativo que paso.

La funcion imprimeDoble sirve con cualquier tipo (de dato) que se pueda imprimir:

   1: >>> imprimeDoble('Jamon')

   2: Jamon Jamon

   3: >>> 

   4: imprimeDoble(5)

   5: 5 5

   6: >>> imprimeDoble(3.14159)

   7: 3.14159 

   8: 3.14159

En la primera llamada a la funcion, el argumento es una cadena; en la segunda es un entero, y en la tercera es un numero de coma °otante.

Las mismas reglas de composicion que se aplican a las funciones internas se aplican tambien a las funciones definidas por el usuario, así que puede usar cualquier tipo de expresion como argumento de imprimeDoble.

   1: >>> imprimeDoble('Jamon'*4)

   2: JamonJamonJamonJamon 

   3: JamonJamonJamonJamon

   4: >>> imprimeDoble(math.cos(math.pi))

   5: -1.0 

   6: -1.0

Como de costumbre, se evalua la expresion antes de ejecutar la funcion, de modo que imprimeDoble devuelve JamonJamonJamonJamon JamonJamonJamonJamon en lugar de ‘Jamon’*4’Jamon’*4.

Asimismo podemos usar una variable como argumento:

   1: >>> latoya = 'Dafne, es mitad laurel mitad ninfa'

   2: >>> 

   3: imprimeDoble(latoya)

   4: Dafne, es mitad laurel mitad ninfa. Dafne, es mitad 

   5: laurel mitad ninfa.

Observe un aspecto realmente importante en este caso: el nombre de la variable que pasamos como argumento (latoya) no tiene nada que ver con el nombre del parámetro (paso). No importa como se llamaba el valor en su lugar original (el lugar desde donde se invoco); aquí en imprimeDoble llamamos a todo el mundo paso.

3.10. Las variables y los parámetros son locales

Cuando crea una variable dentro de una función, solo existe dentro de dicha función, y no puede usarla fuera de ella. Por ejemplo, la función

   1: >>> def catDoble(parte1, parte2):

   2: ... cat = parte1 + parte2

   3: ... 

   4: imprimeDoble(cat)

   5: ...

   6: >>>

toma dos argumentos, los concatena y luego imprime el resultado dos veces.

Podemos llamar a la funcion con dos cadenas:

   1: >>> cantus1 = "Die Jesu domine, "

   2: >>> cantus2 = "Dona eis 

   3: requiem."

   4: >>> catDoble(cantus1, cantus2)

   5: Die Jesu domine, Dona 

   6: eis requiem. Die Jesu domine, Dona eis requiem.

Cuando catDoble termina, la variable cat se destruye. Si tratasemos de imprimirla, obtendríamos un error:

   1: >>> print cat

   2: NameError: cat

Los parametros tambien son locales. Por ejemplo, una vez fuera de la función imprimeDoble, no existe nada llamado paso. Si trata de usarla, Python se quejara.

3.11. Diagramas de pila

Para mantener el rastro de que variables pueden usarse y donde, a veces es útil dibujar un diagrama de pila. Como los diagramas de estado, los diagramas de pila muestran el valor de cada variable, pero también muestran la función a la que cada variable pertenece.

Cada función se representa por una caja con el nombre de la función junto a el. Los parámetros y variables que pertenecen a una función van dentro. Por ejemplo, el diagrama de stack para el programa anterior tiene este aspecto:

image

El orden de la pila muestra el flujo de ejecución. imprimeDoble fue llamado por catDoble y a catDoble lo invoco __main__ , que es un nombre especial de la función mas alta. Cuando crea una variable fuera de cualquier función, pertenece a main

En cada caso, el parámetro se refiere al mismo valor que el argumento correspondiente. Así que parte1 en catDoble tiene el mismo valor que cantus1 en main .

Si sucede un error durante la llamada a una función, Python imprime el nombre de la función y el nombre de la función que la llamo, y el nombre de la función que llamo a esa, y así hasta main .

Por ejemplo, si intentamos acceder a cat desde imprimeDoble, provocaremos un NameError:

   1: Traceback (innermost last):

   2: File "test.py", line 13, in 

   3: __main__

   4: catDoble(cantus1, cantus2)

   5: File "test.py", line 5, in 

   6: catDoble

   7: imprimeDoble(cat)

   8: File "test.py", line 9, in 

   9: imprimeDoble

  10: print cat

  11: NameError: cat

Esta lista de funciones de llama traceback (traza inversa). Le dice a usted en que archivo de programa sucedió el error, y en que línea, y que funciones se ejecutaban en ese momento. También muestra la línea de código que causo el error.

F³jese en la similaridad entre la traza inversa y el diagrama de pila. No es una coincidencia.

3.12. Funciones con resultado

Seguramente ha notado ya que algunas de las funciones que estamos usando, igual que las funciones matemáticas, devuelven un resultado.

Otras funciones, como nueva línea, llevan a cabo una acción pero no devuelven un valor. Ello suscita varias preguntas:

1. ¿Que sucede si llama usted a una función y no hace nada con el resultado (es decir, no lo asigna a una variable ni lo usa como parte de una expresión mas amplia)?

2. ¿Que sucede si usa una función sin resultado como parte de una expresión, por ejemplo nueva línea() + 7?

3. ¿Se pueden escribir funciones que devuelvan resultados, o debemos limitarnos a funciones simples como nueva línea e imprimeDoble?

La respuesta a la tercera pregunta es “sí, puede escribir funciones que devuelvan valores”, y lo haremos en el capítulo 5.

Como actividad final, constaste a las otras dos preguntas intentando hacerlas en la practica. Cada vez que tenga una duda sobre lo que es legal o ilegal en Python, preguntar al interprete será una buena manera de averiguarlo.

3.13. Glosario

llamada a función: Una sentencia que ejecuta una función. Esta compuesta por el nombre de la función mas una lista de argumentos encerrados entre paréntesis.

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.

valor de retorno: Es el resultado de una función. Si se usa una llamada a función a modo de expresión, el valor de retorno es el valor de la expresión.

conversión de tipo: Una sentencia explícita que toma un valor de un tipo y calcula el valor correspondiente de otro tipo.

coerción: Conversión tipos que ocurre automáticamente de acuerdo con las reglas de coerción de Python.

módulo: Fichero que contiene una colección de funciones y clases relacionadas.

notación de punto: La sintaxis para llamar a una función de otro modulo, especificando el nombre del modulo, seguido por un punto y el nombre de la función.

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.

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 a el valor que se le pasa como argumento.

variable local: variable definida dentro de una función. Las variables locales solo pueden usarse dentro de su función.

diagrama de pila: Representación grafica de una pila de funciones, sus variables y los valores a los que se refieren.

traza inversa: (traceback en ingles) Una lista de las funciones en curso de ejecución, presentadas cuando sucede un error en tiempo de ejecución. notación de punto traza inversa

Capítulo 4

Condicionales y

recursividad

 

4.1. El operador modulo

El operador modulo funciona con enteros (y expresiones enteras), y devuelve el resto de dividir el primer operando entre el segundo. En Python, el operador de modulo es el signo de tanto por ciento ( %). La sintaxis es la misma de los otros operadores:

   1: >>> cociente = 7 / 3

   2: >>> print 

   3: cociente

   4: 2

   5: >>> resto = 7 % 3

   6: >>> print resto

   7: 1

Así, 7 dividido entre 3 da 2 con 1 de resto.

El operador de modulo resulta ser soprendentemente util. Por ejemplo, puede comprobar si un numero es divisible entre otro: si x % y es cero, entonces x es divisible entre y.

También puede usar el operador modulo para extraer el dígito mas a la derecha de un numero. Por ejemplo, x % 10 devuelve el dígito mas a la derecha de x (en base 10). De forma similar, x % 100 devuelve los dos últimos dígitos.

Página 33 de 51

Creado con WordPress & Tema de Anders Norén