[Python-es] error bucle for

Chema Cortes py en ch3m4.org
Jue Nov 22 21:26:15 CET 2012


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

El 22/11/12 13:24, Carlos Agulló Calvo escribió:
> he creado el siguiente programita:
> 
> mes_entrada=raw_input ('Escribe un mes de entrada:')
> 
> mes=open(mes_entrada,'r')
> 
> lista_estaciones=[]
> 
> 
> for line in mes: if line[1:8] in lista_estaciones: pass else:
>  lista_estaciones.append(line[1:8])
> 
> 
> for i in lista_estaciones: num_est=str(i) nombre_estacion='est_'  +
> num_est + '.txt' archivo_estacion=open(nombre_estacion,'a')
> 
> *for line in mes:* *        print num_est* *        if line
> [1:8]==num_est:* *            archivo_estacion.write(line)* *
> else:* *            pass* *    archivo_estacion.close*
> 
> mes.close
> 
> y el segundo bucle me falla, puesto que le digo que para cada linea
> del archivo *mes *me mire los caracteres del 2 al 8 y si es igual
> al num_est me lo escriba en el archivo_estacion; pero los archivos
> *est_XXX.txt* que me crea se me quedan vacíos.

Si me permites, hay algunos consejos que quisiera añadir a los ya
dados en los otros mensajes.

Introducir la sentencia "pass" sólo tiene sentido para señalar alguna
parte del código donde piensas añadir código más adelante. No hace
falta que aparezcan en los if..else para completarlos:

    if line[1:8] in lista_estaciones:
        pass
    else:
        lista_estaciones.append(line[1:8])

queda mejor como

    if line[1:8] not in lista_estaciones:
        lista_estaciones.append(line[1:8])

y en el caso de

    if line [1:8]==num_est:
        archivo_estacion.write(line)
    else:
        pass

el else sobraría

    if line [1:8]==num_est:
        archivo_estacion.write(line)


En cuanto a esta expresión

    for i in lista_estaciones:

      num_est=str(i)
      nombre_estacion='est_'  + num_est + '.txt'

es un poco extraña. Parece como que 'i' debería ser un número, pero es
una cadena de 8 caracteres y no me encaja mucho en que los ficheros
sean del estilo 'est_XXX.txt'. Más bien parece como que necesites
pasar a número y no a str:

    nombre_estacion='est_%03d.txt'%int(num_est)


Combinando todo, aquí te pongo un código más concreto para que lo revises:


lista_estaciones=set(line[1:8] for line in open(mes_entrada))

for estacion in lista_estaciones:

    nombre_estacion='est_%03d.txt'%int(estacion)

    with open(nombre_estacion,'a') as salida:

      salida.writelines(
          line for line in open(mes_entrada) if line[1:8]=estacion
      )


Y rizando el rizo, se puede mejorar más todavía con la función
itertools.groupby en un script que roza la magia:

from itertools import groupby

def get_estacion(line):
  return line[1:8]

for est,it in groupby(open(mes_entrada), get_estacion):

    nombre_estacion='est_%03d.txt'%int(est)
    with open(nombre_estacion,"a") as f:
        f.writelines(it)


En esta versión el fichero de entrada sólo se lee una vez y no las N+1
veces (siendo N el número de estaciones) que se lee en el resto de
versiones. A cambio, los ficheros de salida se abren y se cierran
múltiples veces.


Que no te desespere el no comprender estas últimas versiones. Con
tiempo las entenderás. :P


- -- 
Hyperreals *R: http://ch3m4.org/blog
Quarks, bits y otras criaturas infinitesimales
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with undefined - http://www.enigmail.net/

iQEcBAEBAgAGBQJQropYAAoJEFdWyBWwhL4FgDYIAJ3osCrLP2DMnhV8aD9rxegC
B4fa98LdMUkEpWgSVIX2LlrT9i5AdZFx8gyYPV3KN1BeuAVlUeMQ+Z2GPE7O+iW6
1fgpuVG6Qak2OY4hhxf8c1tcp0s53Gj0hJw6YaZ5CoG5d8b9m9FKZfwhJkgQFLHb
py4I0M+5q43+Nktptblh1a4egt/MuFIqjJEXZRJPLgDNMexXL0I7f+rsCpXa3802
M11uqL/6udsNjIGKn3Q0wvjppoWaSzdhivYVOdqXzEAahaupJ1DFblnsYGpBhTSG
QjazmIksB9xN03aHa0XfM2S7mNls3lgAzEs8vkTcdkKhcYqOeLjkO8dQeeW/c1M=
=ZAjK
-----END PGP SIGNATURE-----


Más información sobre la lista de distribución Python-es