Me lo contaron y lo olvidé, lo leí y lo entendí, lo hice y lo aprendí.





sábado, 12 de mayo de 2012

El bucle FOR de Python


Siempre he dicho que python no sería el mejor lenguaje de programación, pero si es único. Unas de sus más grandes "rarezas" es el bucle 'for' el cual no existe como tal (al menos no como en la mayoría de los lenguajes de programación actuales); el 'for' en Python es un "for ... in".
Para quien no sepa cómo funciona el 'for ... in', éste interactúa con lístas (arreglos) en vez de con una sola variable; su sintaxis dice claramente que "por cada 'elemento' en 'tal lista'" realice cierta operación. Con un ejemplo lo dejaré todo claro:

lista=[1,2,3,4]
for numero in lista:
print numero*numero;

El código anterior nos desplegará el siguiente resultado:

1
4
9
16

Como se puede ver, "lista" es una lísta que contiene los número del 1 al 4; lo que hace el for ... in es "descomponer" la lista en los elementos que la conforman y tratar, en cada iteración, cada elemento como la variable número, y dentro del bloque del bucle imprime el cuadrado de cada número o elemento de la lista (o sea que para la primera iteración 'numero' será igual a 1, para la segunda iteración 'numero' será igual a 2, y así para cada elemento de la lista).

Ésto puede sonar bien en primer orden, pero como todo programador estamos acostumbrados a usar el bucle 'for' de la manera tradicional:

for(i=0;i<n;i++)


Por "desgracia" python no cuenta con esta sintaxis, por lo que inicialmente no podemos declarar un valor inicial, un valor final y un incremento/decremento de una variable con la cual interactuar. Posiblemente más de uno haya sustituido el "for" por un "while" en Python, pero ésto, además de ser poco "robusto" para un programador también consume más recursos que un for. La mejor forma de usar un for para las situaciones a las que estamos acostubrados (como por ejemplo, hacer un a[i] y cosas por el estilo) es usar la función "range()" en python combinada con el "for ... in".
La función range() permite generar una lista que vaya desde el primer número que le indiquemos al segundo. Ésta función se puede trabajar de 3 manera, dependiendo la cantidad de parámetros que le pasemos.

Si le pasamos un sólo parámetro, por ejemplo 4 (range(4)), nos arrojará una lista que empieza con el número 0 y terminará con el número 3, incrementándose cada valor de 1 en uno; o sea que la lista final sería:
[0,1,2,3]

Si le pasamos 2 parámentros, por ejemplo 1 y 4 (range(1,4)), nos arrojará una lista que empieza con el primer parámetro (en este caso 1) y terminará un número antes del segundo parámetro (en este caso 4) incrementándose cada valor de 1 en 1; o sea que la lista final sería:
[1,2,3]

Y por último se le puede enviar 3 parámetro, por ejemplo 0,10,2 (range(0,10,2)); el primer parámetro indica en dónde empezará la lista (0), el segundo en dónde terminará (10,recuerden que se detiene un número anterior a éste) y el tercer número indica el incremento entre cáda número (en éste caso 2); así, la lista final será:
[0,2,4,6,8]

para el bucle for... in podemos usar cualquier forma la función range(), pero la forma que más estamos acostumbrados es el tercero, ya que en éste establecemos un valor inicial, uno final y un incremento.
Para el ejemplo inicial podemos hacer lo siguiente:

for i in range(0,4,1):
print lista[i]*lista[i]

y nos dará el mismo resultado que al principio:

1
4
9
16


Ahora bien, aclaremos una cosa, la función range() nos devuelve una lista con tódos los número que le solicitemos dentro de un rango y a intérvalos definidos; o sea que si escribimos

lista=range(0,1000,1)

Nos devolverá una lista con 1000 número (del 0 al 999) lo cual supone un gran e in-necesario gasto de memoria, cosa muy contraria a los bucles "for" de otros lenguajes los cuales solo manejan 1 valor a la vez... pero tranquilos, no es necesario cambiarse de lenguaje y mucho menos volver a recurrir al bucle "while" para evitar tal gasto de memoria en las ocasiones en donde el bucle puede llegar a ser muy grande ya que para ésto tenemos la función xrange() que está hecha precisamente para bucles (y algunas otras cuestiones que no son necesarias mencionar) ya que no crea realmente una lista, sino que en cada iteración va devolviendo el número necesario. Ésto lo podemos hacer si probamos lo siguiente:


print range(0,10,1)
[0,1,2,3,4,5,6,7,8,9]


print xrange(0,10,1)
xrange(0,10,1)


Lo anterior indica que range() nos devuelve la lista completa con todo y el gasto innecesario que con ello conlleva; en cambio xrange() nos devuelve una función, la cual (aun que no se vea en el intérprete) devuelve en cada iteración el número que corresponde a la posición del rango definido; en pocas palabras podemos hacer lo siguiente:

for i in xrange(0,4,1):
print lista[i]*lista[i]

y nos dará el mismo resultado que al principio:

1
4
9
16


Y todo sin ningún gasto innecesario de memoria; de hecho el consumo de recursos es exactamente el mismo que si se hiciera desde C/C++ ya que el bucle "for" está basado en el de C/C++ y la funcion xrand() se interpreta en python (lo que le da velocidad de respuesta).

Bueno, espero que les sirva bastante ésta información, ya que en muchas ocasiones se ve uno en la necesidad de reemplazar un posible "for" con un "while" declarando anteriormente una variable "i" e incrementándola con cada iteración y cosas por el estilo que, además de gastar más recursos de los necesarios, es muy chocante para el programador manejar.

Sigamos teclenado.

Perfil Google+