Autor Tema: Función recursiva que devuelve algo inesperado

0 Usuarios y 1 Visitante están viendo este tema.

17 Marzo, 2015, 10:09 pm
Leído 9835 veces

energy

  • Experto
  • Mensajes: 561
  • Karma: +0/-0
  • Sexo: Masculino
Tengo un problema en python con esta funcion:

def filtrar(linea,palabra1,palabra2,inic):
    m=[]
    l1=linea.find(palabra1,inic)
    l2=linea.find(palabra2,inic)+len(palabra2)-1
    if l1==-1 and l2==-1:
        return m
    else:
        m.append(linea[l1:l2])
        inic+=l2
        posiciones(linea,palabra1,palabra2,inic)

me deberia devolver si la llamo asi:

filtrar('<th>Tipo</th><th>Localizacion</th><th>Uso</th><th>Ministerio</th><th>Superficie</th>','<th>','</th>',0)

lo suyo sería que en m me metiera m=['<th>Tipo</th>,<th>Localizacion</th>,<th>Uso</th>,<th>Ministerio</th>,<th>Superficie</th>']
pero me devuelve una lista vacia m=[]

No veo el error, si fueran tan amables de avistarmelo, gracias y un saludo!

17 Marzo, 2015, 10:23 pm
Respuesta #1

energy

  • Experto
  • Mensajes: 561
  • Karma: +0/-0
  • Sexo: Masculino
Corrijo y actualizo, ahora me sale un bucle de recursión, me dice que hay mas de 200 recursiones y no debería pasar

18 Marzo, 2015, 05:28 am
Respuesta #2

luis

  • Aprendiz
  • Mensajes: 304
  • Karma: +1/-0
  • Sexo: Masculino

tu función está mal escrita. tiene el siguiente aspecto...

Código: [Seleccionar]
def filtrar(linea,palabra1,palabra2,inic):
    m=[]
    ...
    if ...:
        return m
    else:
        m.append(linea[l1:l2])
        inic+=l2
        posiciones(linea,palabra1,palabra2,inic)

observa que si se ejecuta el else la función no devuelve ningún valor.

por otro lado, ¿qué se supone que hace la función posiciones?

saludos

18 Marzo, 2015, 09:22 am
Respuesta #3

energy

  • Experto
  • Mensajes: 561
  • Karma: +0/-0
  • Sexo: Masculino
Si se ejecuta el else, vuelve a llamarse a si misma hasta que l1 o l2 sean -1. Pues lo que hace es dado un string, y dos palabras, copia lo que hay entre esas dos palabras, incluidas ambas en una lista.
Saludos.

18 Marzo, 2015, 12:51 pm
Respuesta #4

luis

  • Aprendiz
  • Mensajes: 304
  • Karma: +1/-0
  • Sexo: Masculino
Si se ejecuta el else, vuelve a llamarse a si misma hasta que l1 o l2 sean -1.

si eso es lo que quieres, seguramente querés escribir
Código: [Seleccionar]
filtrar en lugar de
Código: [Seleccionar]
posiciones.

saludos

18 Marzo, 2015, 04:20 pm
Respuesta #5

energy

  • Experto
  • Mensajes: 561
  • Karma: +0/-0
  • Sexo: Masculino
Sisi, puse filtrar, fue error mio al copiarlo aqui, pero me da ese error saludos

18 Marzo, 2015, 04:24 pm
Respuesta #6

luis

  • Aprendiz
  • Mensajes: 304
  • Karma: +1/-0
  • Sexo: Masculino
Sisi, puse filtrar, fue error mio al copiarlo aqui, pero me da ese error saludos

¿o sea que tu código termina con el texto

Código: [Seleccionar]
        return filtro (linea,palabra1,palabra2,inic)
¿no te olvidaste el return?


18 Marzo, 2015, 04:27 pm
Respuesta #7

luis

  • Aprendiz
  • Mensajes: 304
  • Karma: +1/-0
  • Sexo: Masculino
por cierto, la condición sobre l2 en la guarda es incorrecta. creo que siempre devuelve false, y eso explica el nido recursivo.


18 Marzo, 2015, 05:54 pm
Respuesta #8

energy

  • Experto
  • Mensajes: 561
  • Karma: +0/-0
  • Sexo: Masculino

18 Marzo, 2015, 07:45 pm
Respuesta #9

luis

  • Aprendiz
  • Mensajes: 304
  • Karma: +1/-0
  • Sexo: Masculino
estoy seguro que el valor que le asignas siempre es mayor que -1

18 Marzo, 2015, 08:22 pm
Respuesta #10

energy

  • Experto
  • Mensajes: 561
  • Karma: +0/-0
  • Sexo: Masculino
Pero porque? Si llegara un momento en el que no encuentre la palabra y entonces se saldra del bucle.

18 Marzo, 2015, 08:48 pm
Respuesta #11

luis

  • Aprendiz
  • Mensajes: 304
  • Karma: +1/-0
  • Sexo: Masculino
Código: [Seleccionar]
def filtrar(linea,palabra1,palabra2,inic):
    m=[]
    l1=linea.find(palabra1,inic)
    l2=linea.find(palabra2,inic)+len(palabra2)-1
...

cuando linea.find(palabra2,inic) es -1, ¿qué valor toma l2?

18 Marzo, 2015, 11:11 pm
Respuesta #12

energy

  • Experto
  • Mensajes: 561
  • Karma: +0/-0
  • Sexo: Masculino
Ahh claro joder que fallo mas tonto, entonces modificaré el append cierto, ahora pruebo y os cuento, saludos.

18 Marzo, 2015, 11:50 pm
Respuesta #13

energy

  • Experto
  • Mensajes: 561
  • Karma: +0/-0
  • Sexo: Masculino
m=[]
def posiciones(linea,palabra1,palabra2,inic):
    l1=linea.find(palabra1,inic)
    l2=linea.find(palabra2,inic)+len(palabra2)
       
    if l1==-1 or l2==-1:
        return m
    else:
        m.append(linea[l1:l2])
        inic+=l2-1
        return posiciones(linea,palabra1,palabra2,inic)
       
Este es el codigo bueno jejeje, pero ahora el problema es que cuando la llamo no me devuelve la última palabra, le faltaría por añadir superficie

posiciones('<th>Tipo</th><th>Localizacion</th><th>Uso</th><th>Ministerio</th><th>Superficie</th>','<th>','</th>',0)
Out[11]: ['<th>Tipo</th>', '<th>Localizacion</th>', '<th>Ministerio</th>']

19 Marzo, 2015, 12:37 am
Respuesta #14

luis

  • Aprendiz
  • Mensajes: 304
  • Karma: +1/-0
  • Sexo: Masculino

el código último también tiene detalles. ahora no puedo comentar. luego escribo.


19 Marzo, 2015, 12:47 am
Respuesta #15

energy

  • Experto
  • Mensajes: 561
  • Karma: +0/-0
  • Sexo: Masculino
Vale, el error es que inic=l2+... tenia que quitar el inic, ahora lo que tengo que hacer será quitar las etiquetas html

19 Marzo, 2015, 01:29 am
Respuesta #16

luis

  • Aprendiz
  • Mensajes: 304
  • Karma: +1/-0
  • Sexo: Masculino
en esta respuesta voy a criticar tu uso de la variable l2.

en la siguiente línea, l2 se usa para indicar que el tag palabra2 no aparece en linea.

Código: [Seleccionar]
if l1==-1 or l2==-1:
sin embargo, en la siguiente línea se usa para indicar la posición en que termina palabra2.

Código: [Seleccionar]
        m.append(linea[l1:l2])

o sea, usas la misma variable para indicar dos cosas bien distintas. te sugiero que la inicialices con la idea más simple, y que compliques su uso luego. es decir, te sugiero el siguiente cambio.

Código: [Seleccionar]
    ...
   l2=linea.find(palabra2,inic)
       
    if l1==-1 or l2==-1:
        return m
    else:
        m.append(linea[l1:l2+len(palabra2)])
       ....

posiblemente debas modificar también la línea

Código: [Seleccionar]
        inic+=l2-1

por otro lado, no parece pertinente usar la variable m como global.

fijate lo que señalé, y revisa el código, si quieres que le eche otro vistazo.

saludos


19 Marzo, 2015, 01:47 am
Respuesta #17

energy

  • Experto
  • Mensajes: 561
  • Karma: +0/-0
  • Sexo: Masculino
Vale, gracias ya solucioné casi todo, ahora el problema es en esta última función, que dada una url, y 4 etiquetas: las 2 primeras indican desde que linea hasta que linea quiero buscar lo que voy a copiar, y las dos siguientes son las etiquetas que delimitan los elementos que voy a añadir a mi lista, entonces doy esto:

m=[]
def posiciones(linea,palabra1,palabra2,inic):
    l1=linea.find(palabra1,inic)
    l2=linea.find(palabra2,inic)
       
    if l1==-1 or l2==-1:
        return m
    else:
        m.append(linea[l1:l2+len(palabra2)])
        inic=l2+len(palabra2)-1
        return posiciones(linea,palabra1,palabra2,inic)
def limpia(lista):
    nuevalista=[]
    for i in m:
        nuevalista.append(clean(i))
    return nuevalista
def encuentrainiciocopiar(lineas,etiqueta1,etiqueta2):
    lineaquemiro=1
    x=0
    for linea in lineas:
        if linea.find(etiqueta1)!=-1:
            x=lineaquemiro
        lineaquemiro+=1
    y=0
    lineaquemiro2=1
    for linea in lineas:
        if linea.find(etiqueta2)!=-1:
            y=lineaquemiro2
        lineaquemiro2+=1
    return x,y
def enlistar(url,etiqueta1,etiqueta2,etiqueta3,etiqueta4):
    texto=urllib.urlopen(url)
    lineas=texto.readlines()
    i,j=encuentrainiciocopiar(lineas,etiqueta1,etiqueta2)
    for linea in range(i,j+1):
        l=posiciones(linea,etiqueta3,etiqueta4,0)
    return l

Y me dan estos errores:
enlistar('http://transparencia.gob.es/es_ES/buscar/contenido/cibi/CIBI_DPTO26','<thead>','</thead>','<th>','</th>')
Traceback (most recent call last):

  File "<ipython-input-64-40457839f07a>", line 1, in <module>
    enlistar('http://transparencia.gob.es/es_ES/buscar/contenido/cibi/CIBI_DPTO26','<thead>','</thead>','<th>','</th>')

  File "C:/Users/Adri/Desktop/clean.py", line 53, in enlistar
    l=posiciones(linea,etiqueta3,etiqueta4,0)

  File "C:/Users/Adri/Desktop/clean.py", line 20, in posiciones
    l1=linea.find(palabra1,inic)

AttributeError: 'int' object has no attribute 'find'
Me debería dar esta lista:

['<th>Tipo</th>',
 '<th>Localizacion</th>',
 '<th>Uso</th>',
 '<th>Ministerio</th>',
 '<th>Superficie</th>']

Ahora si que no veo el error, un saludo!

19 Marzo, 2015, 01:53 am
Respuesta #18

luis

  • Aprendiz
  • Mensajes: 304
  • Karma: +1/-0
  • Sexo: Masculino

me parece sano eliminar la variable global m


19 Marzo, 2015, 02:06 am
Respuesta #19

energy

  • Experto
  • Mensajes: 561
  • Karma: +0/-0
  • Sexo: Masculino
Si elimino la lista vacia m no podría meter en ninguna lista, los append que tengo por ahi, eso no me vale, si puedes ver el error de los int que me está dando...Saludos!