2009-12-11 13 views
12

Un programma Python che sto scrivendo è di leggere un determinato numero di righe dalla cima di un file e il programma deve conservare questa intestazione per uso futuro. Attualmente, sto facendo qualcosa di simile al seguente:Modo Pythonic da ignorare per variabile controllo loop

header = '' 
header_len = 4 
for i in range(1, header_len): 
    header += file_handle.readline() 

pylint lamenta che non sto usando la variabile i. Quale sarebbe un modo più pitonioso per fare questo?

Modifica: Lo scopo del programma è dividere in modo intelligente il file originale in file più piccoli, ognuno dei quali contiene l'intestazione originale e un sottoinsieme di dati. Quindi, ho bisogno di leggere e conservare solo l'intestazione prima di leggere il resto del file.

risposta

11
f = open('fname') 
header = [next(f) for _ in range(header_len)] 

Dal momento che si sta andando a dare un colpo di testa di nuovo ai nuovi file, non c'è bisogno di fare qualsiasi cosa con esso. Per scrivere di nuovo al nuovo file:

open('new', 'w').writelines(header + list_of_lines) 

se si conosce il numero di righe nel file vecchio, list_of_lines sarebbe diventato:

list_of_lines = [next(f) for _ in range(chunk_len)] 
+3

Avanti semplice, facilmente comprensibile ed elimina il reclamo di reclamo. Quindi è la migliore risposta, IMO. – GreenMatt

+0

Non vuoi chiudere il nuovo file? ;) – ThiefMaster

1

Può essere questo:

header_len = 4 
header = open("file.txt").readlines()[:header_len] 

Ma, sarà fastidioso per i file lunghi.

+5

.readlines() legge l'intero file, anche se .. se si dispone di un file di grandi dimensioni e non si desidera leggere il tutto in memoria, questa potrebbe essere una cattiva idea –

+0

sì, ho aggiunto che mentre stavi scrivendo questo,;) – mshsayem

+1

se solo readlines() erano pigri! –

11

Non sono sicuro di quali siano le regole di Pylint, ma è possibile utilizzare il nome della variabile "_".

header = '' 
header_len = 4 
for _ in range(1, header_len): 
    header += file_handle.readline() 
+0

Non è necessario utilizzare il ciclo for. Raccomando una comprensione delle liste (vedi il mio post qui sotto). Buona call sulla variabile throwaway, però. – Escualo

+0

@ Poger patè: puoi spiegare? – Escualo

+0

@Arrieta cosa c'è di sbagliato nei loop? –

10
import itertools 

header_lines = list(itertools.islice(file_handle, header_len)) 
# or 
header = "".join(itertools.islice(file_handle, header_len)) 

Si noti che con il primo, i caratteri di nuova riga sarà ancora presente, per togliere loro:

header_lines = list(n.rstrip("\n") 
        for n in itertools.islice(file_handle, header_len)) 
+0

Se si eliminano le righe, sarà difficile richiamare la struttura dell'intestazione originale. Ti raccomando di tenerli. – Escualo

+0

No, non lo farà. In questo esempio sono memorizzati in una lista piuttosto che in una stringa lunga. Quale dovrebbe usare dipende da ciò che sta facendo con i dati più tardi. –

+0

L'OP scrive nel suo script 'header + = ...' quindi penso che intendesse una singola stringa, ma hai ragione: dipende. – Escualo

4

La mia migliore risposta è la seguente:

file di test.dat :

This is line 1 
This is line 2 
This is line 3 
This is line 4 
This is line 5 
This is line 6 
This is line 7 
This is line 8 
This is line 9 

Python scri pt:

f = open('test.dat') 
nlines = 4 
header = "".join(f.readline() for _ in range(nlines)) 

uscita:

>>> header 
'This is line 1\nThis is line 2\nThis is line 3\nThis is line 4\n' 

Si noti che non è necessario chiamare tutti i moduli; anche che è possibile utilizzare qualsiasi variabile fittizia al posto di _ (funziona con i o j o ni o qualsiasi altra cosa) ma io raccomando di non farlo (per evitare confusione). È possibile rimuovere i caratteri di nuova riga (anche se non è consigliabile farlo - in questo modo è possibile distinguere tra le righe) o fare qualsiasi cosa che si possa fare con le stringhe in Python.

Si noti che non ho fornito una modalità per l'apertura del file, quindi il suo valore predefinito è "sola lettura" - questo non è Pythonic; in Python "esplicito è meglio di implicito". Alla fine, le persone simpatiche chiudono i loro file; in questo caso è automatico (perché lo script termina) ma è consigliabile chiuderli usando f.close().

Happy Pythoning.

Modifica: Come sottolineato da Roger Pate, le parentesi quadre non sono necessarie nella comprensione della lista, riducendo quindi la linea di due caratteri. Lo script originale è stato modificato per riflettere questo.

+2

Quando non hai realmente bisogno di una lista e qualsiasi iterabile funzionerà, come il parametro su "" .join' qui, allora un'espressione di generatore è migliore, più semplice (di due tasti); e più chiara di una lista comprensione: '" ".join (..)' invece di '" ".join ([..])'. Sono correlati, e un LC è in realtà un caso speciale di un genexp (almeno a mio avviso), in cui '[..]' è solo la convenienza di 'list (..)'. http://www.python.org/dev/peps/pep-0289/ –

+0

Questo è fantastico - ogni giorno impari: +1 – Escualo

+0

chiudi il file handle – ghostdog74

-1
s="" 
f=open("file") 
for n,line in enumerate(f): 
    if n<=3 : s=s+line 
    else: 
     # do something here to process the rest of the lines   
print s 
f.close() 
+0

Sembra che voglia il risultato in una singola stringa (nota che scrive header + = ...) – Escualo

+0

Da He I significa l'OP – Escualo

+1

Penso che questa implementazione sia eccessivamente complicata per un compito così semplice; si legge come C su Python - sfrutta la filosofia "Batterie incluse" e usa i metodi esistenti sugli oggetti. – Escualo

1

Non vedo nulla di sbagliato con la soluzione, può essere solo sostituire i con _, anche io non mi piace invocare itertools ovunque dove soluzione più semplice funziona, è come le persone che utilizzano jQuery per compiti javascript banali .in ogni caso solo per avere itertools vendetta qui è la mia soluzione

come si desidera leggere tutta la linea comunque il file per riga, perché non solo prima leggere l'intestazione e dopo che fare quello che vuoi fare

header = '' 
header_len = 4 

for i, line in enumerate(file_handle): 
    if i < header_len: 
     header += line 
    else: 
     # output chunks to separate files 
     pass 

print header 
0

Che dire :

header = [] 
for i,l in enumerate(file_handle): 
    if i <= 3: 
     header += l 
     continue 
    #proc rest of file here 
0

Un problema con l'utilizzo _ come una variabile dummy è che risolve il problema solo su un livello, considera qualcosa come il seguente.

def f(n, m): 
"""A function to run g() n times and run h() m times per g.""" 
    for _ in range(n): 
     g() 
     for _ in range(m): 
      h() 
    return 0 

Questa funzione funziona bene, ma il _ iteratore su m corre è problematica come può entrare in conflitto con la parte superiore del _. In ogni caso PyCharm si lamenta di questo tipo di sintassi.

Quindi vorrei dire che _ non è come "usa e getta" come suggerito in precedenza.

Forse ti piacerebbe solo creare una funzione per farlo!

def run(f, n, *args): 
    """Runs f with the arguments from the args tuple n times.""" 
    for _ in range(n): 
     f(*args) 

esempio si potrebbe usare in questo modo:

>>> def ft(x, L): 
...  L.append(x) 

>>> a = 7 
>>> nums = [4, 1] 
>>> run(ft, 10, a, nums) 
>>> nums 
[4, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7] 
Problemi correlati