[Python] saluti e prima domanda sulle list comprhension
Enrico Franchi
enrico.franchi a gmail.com
Dom 27 Gen 2008 18:10:19 CET
On Jan 27, 2008, at 5:34 PM, Java wrote:
> Salve a tutti, sono nuovo di questa mailing list e del pythone più in
> generale!
Io suggerirei di cambiare nome. <g> :)
> Prima di fare la domanda, preannuncio che mi sono occupato di questa
> cosa per un paio di giorni, e che essendo completamente niubbo con il
> python potrei aver fatto qualche cavolata :-D
Il che è naturale e altrimenti non posteresti qui. Aggiungo inoltre...
la prima cavolata che i principianti fanno è applicare in toto
strutture mentali che provengono da altri linguaggi.
> Veniamo alla nota dolente, devo fare un progetto per
> l'università(costruire una rete sociale di video di youtube) che
> comporta anche la scrittura di un piccolo crawler. Ho pensato di usare
> python sostanzialmente perché non lo conoscevo, e così approfitto
> dell'esame per imparare un nuovo linguaggio...
Interessante e ottimo proposito.
> Senza entrare troppo nei dettagli, ho fatto un thread che si occupa di
> fare il crawling di una pagina iterando per in base alla profondità di
> crawling.
Male: perché usare un thread? Ogni programmatore che si rende conto
che spesso e volentieri i thread sono la risposta sbagliata ad un non
problema è una speranza per un futuro migliore.
Diciamocela tutta: se in Java si programma con i thread (a memoria
condivisa), questo non vuole dire che debba essere buona pratica
ovunque. Io in particolare per quello che fai tu userei multiprocesso.
No: mento sapendo di mentire, forse userei un'altra cosa, ma non
voglio complicarti ora la vita.
> def run ( self ):
> # lista temporanea
> temp = []
> # all'inizio la lista results contine l'url iniziale
> results = [self.start_url]
> #cast della profondita' in intero poiché la leggo da input
> p = int(self.profondita)
brrr... ma così, dentro un thread prendi input da un utente?
Se l'input lo prendi fuori, falla *fuori* la conversione,
eventualmente con un gestore di eccezioni.
>
> # finche' la profondita' e' maggiore di zero, intero sulla lista
> temp eseguendo il
> # parsing degli url trovati in essa
> while(p > 0):
> print "Thread lanciato con profondita: ", p
> # copio i risultati attuali dentro la lista temp
> # all'inizio conterrà solo un url
> temp = results
> print "ecco la lista TEMP:"
> print temp
> [results.extend(self.parseUrl(video)) for video in temp]
> print "finito ciclo while \n\n\n" # qua non ci arrivo
> mai :-(
> p-=1
>
> il problema è che in ogni caso non esce mai dalla list comphrension,
> eppure la lista temp contiene un solo url!
Ehm. Guarda che fai: temp = results. Per cui entrambi puntano allo
stesso oggetto.
A questo punto hai un ciclo che per ogni video che trova in temp,
aggiunge una cosa a results.
Ovvero a temp.
Una nota stilistica: l'uso che fai della list comprehension è IMHO
sbagliato. Una list comprehension (pur essendo completamente generale)
tipicamente viene usata per generare un nuovo array. Ha insomma un
significato in cui il valore di ritorno della funzione ha *profondo*
significato (e spesso questo nuovo array viene manipolato in seguito).
Tu invece la stai chiamando con un metodo che restituisce None. Il tuo
codice anche se funzionasse, sarebbe 'bruttino'. Riscriviamolo con un
for.
for video in temp:
results.extend(self.parseUrl(vide))
Ecco... ora dovrebbe essere chiaro l'inghippo. Guarda questo codice
(viene dall'interprete interattivo ipython):
In [58]: a = ["x"]
In [59]: for el in a:
....: print a
....: a.append(el)
....:
['x']
['x', 'x']
['x', 'x', 'x']
['x', 'x', 'x', 'x']
['x', 'x', 'x', 'x', 'x']
['x', 'x', 'x', 'x', 'x', 'x']
['x', 'x', 'x', 'x', 'x', 'x', 'x']
Questo è evidentemente e ovviamente sbagliato. Ora rendiamolo più
simile al tuo codice:
In [62]: a = ["x"]
In [63]: b = a
In [65]: id(a) == id(b)
Out[65]: True
In [66]: print id(a), id(b)
7864368 7864368
In [67]: for el in a:
....: print a
....: b.append(el)
....:
['x']
['x', 'x']
['x', 'x', 'x']
['x', 'x', 'x', 'x']
['x', 'x', 'x', 'x', 'x']
Cioè tu iteri su qualcosa, ma aggiungi ad ogni iterazione un elemento.
Ovvio che non termini.
> In pratica continua a ciclare come se ogni volta eseguisse temp =
> results, ma non capisco il perché...
Ti suggerisco di studiarti bene i fondamentali. Ti saresti reso conto
che dopo avere fatto temp = results, entrambi sono riferimenti allo
stesso oggetto. Da cui modificando attraverso uno quell'oggetto, la
modifica la vedi anche sull'altro.
More information about the Python
mailing list