Herramientas Informaticas

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

7.3. Recorrido y el bucle for

Muchos cálculos incluyen el proceso de una cadena carácter a carácter. A menudo empiezan por el principio, seleccionan cada carácter por turno, hacen algo con el y siguen hasta el final. Este patrón de proceso se llama recorrido. Una forma de codificar un recorrido es una sentencia while:

   1: indice = 0

   2: while indice < len(fruta):

   3:     letra = fruta[indice]

   4:     print 

   5:     letra

   6:     indice = indice + 1

Este bucle recorre la cadena y muestra cada letra en una línea distinta. La condición del bucle es indice < len(fruta), de modo que cuando indice es igual a la longitud de la cadena, la condicion es falsa y no se ejecuta el cuerpo del bucle. El ultimo caracter al que se accede es el que tiene el índice len(fruta)-1, que es el ultimo caracter de la cadena.

Como ejercicio, escriba una función que tome una cadena como argumento y entregue las letras en orden inverso, una por línea.

Es tan habitual usar un índice para recorrer un conjunto de valores que Python facilita una sintaxis alternativa mas simple: el bucle for:

   1: for car in fruta:

   2: print car

Cada vez que recorremos el bucle, se asigna a la variable car el siguiente carácter de la cadena. El bucle continua hasta que no quedan caracteres.

El ejemplo siguiente muestra como usar la concatenacion junto a un bucle for para generar una serie abecedarica. “Abecedarica” es la serie o lista en la que cada uno de los elementos aparece en orden alfabetico. Por ejemplo, en el libro de Robert McCloskey Make Way for Ducklings (Dejad paso a los patitos), los nombres de los patitos son Jack, Kack, Lack, Mack, Nack, Ouack, Pack, y Quack.

Este bucle saca esos nombres en orden:

   1: prefijos = "JKLMNOPQ"

   2: sufijo = "ack"

   3: for letra in prefijos:

   4: print letra 

   5: + sufijo

   6: La salida del programa 

   7: es:

   8: Jack

   9: Kack

  10: Lack

  11: Mack

  12: Nack

  13: Oack

  14: Pack

  15: Qack

Por supuesto, esto no es del todo correcto, porque “Ouack” y “Quack” no están correctamente escritos.

Como ejercicio, modifique el programa para corregir este error.

7.8. Bucles y conteo

El programa que sigue cuenta el numero de veces que la letra a aparece en una
cadena:

   1: fruta = "banana"

   2: cuenta = 0

   3: for car in fruta:

   4: if car == 'a':

   5: cuenta 

   6: = cuenta + 1

   7: print cuenta

Este programa muestra otro patron de computacion llamado contador. La variable cuenta se incializa a 0 y luego se incrementa cada vez que se encuentra una a. (Incrementar es aumentar en uno; es lo contario de decrementar, y sin relacion alguna con “excremento”, que es un nombre.) Al salir del bucle, cuenta contiene el resultado – el numero total de aes.

Como ejercicio, encapsule este codigo en una funcion llamada cuentaLetras, y generalícela de forma que acepte la cadena y la letra como parametros.

Como un segundo ejercicio, reescriba esta funcion para que en lugar de recorrer la cadena, use la version de tres parametros de encuentra del anterior.

7.11. Glosario

tipo de datos compuesto: Un tipo de datos en el que los valores están hechos de componentes o elementos que son a su vez valores.

recorrer: Realizar de forma iterativa una operación similar sobre cada uno de los elementos de un conjunto.

índice: Una variable o valor usado para seleccionar un miembro de un conjunto ordenado, como puede ser un carácter de una cadena.

porción: Una parte de una cadena especificada por un intervalo de índices.

mutable: Un tipo de datos compuesto a cuyos elementos se les puede asignar nuevos valores.

contador: Una variable usada para contar algo, normalmente inicializado a cero e incrementado posteriormente.

8.9. Borrado en una lista

El uso de porciones para borrar elementos de una lista puede ser extraño, y por ello propicio a los errores. Python nos da una alternativa que resulta mas legible.

del elimina un elemento de una lista:

   1: >>> a = ['uno', 'dos', 'tres']

   2: >>> del a[1]

   3: >>> a

   4: ['uno', 'tres']

Como podría esperar, del maneja índices negativos y provoca un error en tiempo de ejecución sin el índice esta fuera de límites.

Puede usar una porción como índice para del:

   1: >>> lista = ['a', 'b', 'c', 'd', 'e', 'f']

   2: >>> del lista[1:5]

   3: >>> print lista

   4: ['a', 'f']

Como es habitual, las porciones seleccionan todos los elementos hasta, pero no incluido, el segundo índice.

8.14. Listas anidadas

Una lista anidada es una lista que aparece como elemento dentro de otra lista.

En esta lista, el tri-esimo elemento es una lista anidada:

   1: >>> lista = ["hola", 2.0, 5, [10, 20]]

Si imprimimos lista[3], obtendremos [10, 20]. Para extraer los elementos de la lista anidada, podemos proceder en dos pasos:

   1: >>> elt = lista[3]

   2: >>> elt[0]

   3: 10

O podemos combinarlos:

   1: >>> lista[3][1]

   2: 20

Los operadores corchete se evalúan de izquierda a derecha, as³ que esta expresión saca el tri-esimo elemento de lista y luego extrae el unesimo elemento de ella.

9.2. Asignación de tuplas

De vez en cuando, es útil intercambiar los valores de dos variables. Para hacerlo con sentencias de asignación convencionales debemos usar una variable temporal. Por ejemplo, para intercambiar a y b:

   1: >>> temp = a

   2: >>> a = b

   3: >>> b = temp

Si tenemos que hacer esto a menudo, esta aproximación resulta aparatosa. Python proporciona una forma de asignación de tuplas que soluciona este problema elegantemente:

   1: >>> a, b = b, a

El lado izquierdo es una tupla de variables, el lado derecho es una tupla de valores. Cada valor se asigna a su respectiva variable. Todas las expresiones del lado derecho se evalúan antes de las asignaciones. Esta característica hace de la asignación de tuplas algo muy versátil.

Naturalmente, el número de variables a la izquierda y el número de valores a la derecha deben ser iguales:

   1: >>> a, b, c, d = 1, 2, 3

   2: ValueError: unpack tuple of wrong size

9.3. Tuplas como valor de retorno

Las funciones pueden devolver tuplas como valor de retorno. Por ejemplo, podría escribir una función que intercambie dos parámetros:

   1: def intercambio(x, y):

   2:     return y, x

Luego podemos asignar el valor de retorno a una tupla con dos variables:

   1: a, b = intercambio(a, b)

En este caso, no hay ninguna ventaja en convertir intercambio en una función.
De hecho, existe un peligro al intentar encapsular intercambio, y es el tentador error que sigue:

   1: def intercambio(x, y): # versión incorrecta

   2: x, y = y, x

Si llamamos a esta función así:

   1: intercambio(a, b)

a y x son alias del mismo valor. Cambiar x dentro de intercambio hace que x se refiera a un valor diferente, pero no tiene efecto alguno sobre a en main .

De forma similar, cambiar y no tiene efecto sobre b.

Esta función se ejecuta sin generar un mensaje de error, pero no hace lo que intentamos. Este es un ejemplo de error semántico.

A modo de ejercicio, dibuje un diagrama de estados para esta función de manera que pueda ver por que no trabaja como usted quiere.

9.4. Números aleatorios

La mayor parte de los programas hacen lo mismo cada vez que los ejecutamos, por lo que se dice que son deterministas.

Normalmente el determinismo es una cosa buena, ya que esperamos que un calculo nos de siempre el mismo resultado.

Para algunas aplicaciones, sin embargo, queremos que el computador sea impredecible. El ejemplo obvio son los juegos, pero hay mas.

Hacer que un programa sea realmente no determinista resulta no ser tan sencillo, pero hay formas de que al menos parezca no determinista. Una de ellas es generar números aleatorios y usarlos para determinar el resultado del programa.

Python proporciona una función interna que genera números pseudoaleatorios, que no son verdaderamente aleatorios en un sentido matemático, pero servirán para nuestros propósitos.

El modulo random contiene una función llamada random que devuelve un numero en coma flotante entre 0,0 y 1,0. Cada vez que usted llama a random obtiene el siguiente numero de una larga serie. Para ver un ejemplo, ejecute este bucle:

   1: import random

   2:  

   3: for i in range(10):

   4:     x = random.random()

   5:     print x

Para generar un numero aleatorio entre 0,0 y un límite superior como maximo, multiplique x por maximo.

Como ejercicio, genere un numero aleatorio entre minimo y maximo.
Como ejercicio adicional, genere un numero aleatorio entero entre minimo y maximo, incluyendo ambos extremos.

9.5. Lista de números aleatorios

El primer paso es generar una lista de valores aleatorios. listaAleatorios acepta un parámetro entero y devuelve una lista de números aleatorios de la longitud dada. Comienza con una lista de n ceros. Cada vez que ejecuta el bucle, sustituye uno de los elementos con un numero aleatorio. El valor de retorno es una referencia a la lista completa:

   1: def listaAleatorios(n):

   2: s = [0] * n

   3: for i in range(n):

   4: s[i] = random.random()

   5: return s

Vamos a probar esta función con una lista de ocho elementos. A la hora de depurar es una buena idea empezar con algo pequeño.

   1: >>> listaAleatorios(8)

   2: 0.15156642489

   3: 0.498048560109

   4: 0.810894847068

   5: 0.360371157682

   6: 0.275119183077

   7: 0.328578797631

   8: 0.759199803101

   9: 0.800367163582

Se supone que los números generados por random están distribuidos uniformemente, lo que significa que cada valor es igualmente probable.

Si dividimos el intervalo de valores posibles en “baldes” de igual tamaño y contamos el numero de veces que un valor cae en cada balde, deberemos tener mas o menos el mismo numero en todos.

Podemos contrastar esta teor³a escribiendo un programa que divida el intervalo en baldes y contando el numero de valores en cada uno.

9.6. Conteo

Un buen enfoque sobre problemas como este es dividir el problema en subproblemas que encajen en un esquema computacional que hayamos visto antes.

En este caso, queremos recorrer una lista de números y contar el numero de veces que un valor cae en un intervalo dado.

Eso nos suena. En la Sección 7.8 escribimos un programa que recorr³a una cadena de texto y contaba el numero
de veces que aparecía una letra determinada.

Así, podemos hacerlo copiando el programa viejo y adaptándolo al problema actual. El programa original era:

   1: cuenta = 0

   2: for car in fruta:

   3:     if car == 'a':

   4:         cuenta = cuenta + 1

   5: print cuenta

El primer paso es sustituir fruta con lista y car con núm. Esto no cambia el programa, solo lo hace mas legible.

El segundo paso es cambiar la comprobación. No estamos interesados en encontrar letras. Queremos ver si num esta entre los valores de mínimo y máximo.

   1: cuenta = 0

   2: for num in lista

   3:     if minimo < num < maximo:

   4:         cuenta = cuenta + 1

   5: print cuenta

El ultimo paso es encapsular este código en una función llamada enElBalde.

Los parámetros son la lista y los valores minimo y maximo.

   1: def enElBalde(lista, minimo, maximo):

   2:     cuenta = 0

   3:     for num in lista:

   4:             if minimo < num < maximo:

   5:                 cuenta = cuenta + 1

   6:     return cuenta

Copiar y modificar un programa existente nos facilita escribir esta función rápidamente y nos ahorra un montón de tiempo de depuración. Este plan de desarrollo se llama coincidencia de esquemas. Si se encuentra trabajando en un
problema que ya soluciono, reutilice la solución.

Página 36 de 51

Creado con WordPress & Tema de Anders Norén