2015-08-14 10 views
6

Qual è il modo divinatorio per PEP-8-Ify come ad esempio con la dichiarazione:Mantenendo il margine di 80 caratteri a lungo con la dichiarazione?

with tempfile.NamedTemporaryFile(prefix='malt_input.conll.', dir=self.working_dir, mode='w', delete=False) as input_file, tempfile.NamedTemporaryFile(prefix='malt_output.conll.', dir=self.working_dir, mode='w', delete=False) as output_file: 
    pass 

avrei potuto fare questo, ma dal momento che il tempfile I/O non è con l'affermazione with, lo fa chiude automaticamente dopo la con ? È che divinatorio ?:

intemp = tempfile.NamedTemporaryFile(prefix='malt_input.conll.', dir=self.working_dir, mode='w', delete=False) 

outtemp = tempfile.NamedTemporaryFile(prefix='malt_output.conll.', dir=self.working_dir, mode='w', delete=False) 

with intemp as input_file, outtemp as output_file: 
    pass 

Oppure potrei usare barre:

with tempfile.NamedTemporaryFile(prefix='malt_input.conll.', 
dir=self.working_dir, mode='w', delete=False) as input_file, \ 
tempfile.NamedTemporaryFile(prefix='malt_output.conll.', 
dir=self.working_dir, mode='w', delete=False) as output_file: 
    pass 

Ma è che PEP8 rispetti-grado? Quello è pythonic?

+1

C'è una sezione in [PEP8] (https://www.python.org/dev/peps/pep-0008/#maximum-line-length) sulla lunghezza massima delle linee – GP89

+1

[Oltre PEP8] (https: // www.youtube.com/watch?v=wf-BqAjZb8M)! – mkrieger1

+1

possibile duplicato di [Come rompere un lungo con l'istruzione in python] (http://stackoverflow.com/questions/16080049/how-to-break-a-long-with-statement-in-python) – mkrieger1

risposta

3

PEP 0008 does say it's ok per utilizzare le barre rovesciate per una riga with.

Le barre rovesciate possono essere ancora appropriate a volte. Ad esempio, long, multiple with -statements non possono utilizzare la continuazione implicita, quindi i backslash sono accettabili.

Anche se si raccomanda che sia rientrato, quindi la tua linea dovrebbe essere simile a questo:

with tempfile.NamedTemporaryFile(prefix='malt_input.conll.', 
     dir=self.working_dir, mode='w', delete=False) as input_file, \ 
     tempfile.NamedTemporaryFile(prefix='malt_output.conll.', 
     dir=self.working_dir, mode='w', delete=False) as output_file: 
    pass 

Si consiglia di tenerlo rientrato una quantità nettamente diverso di spazio per il seguente blocco di codice, quindi è più chiaro dove finisce con la linea e inizia il blocco.

Tuttavia non è in realtà necessità di utilizzare slash se racchiudere i parametri tra parentesi

with (tempfile.NamedTemporaryFile(prefix='malt_input.conll.', 
     dir=self.working_dir, mode='w', delete=False)) as input_file, (
     tempfile.NamedTemporaryFile(prefix='malt_output.conll.', 
     dir=self.working_dir, mode='w', delete=False)) as output_file: 
    pass 

che non dipendono dalla vostra disposizione frase esatta del corso e la vostra situazione potrebbe essere diversa se avere una staffa alla fine di una riga è meglio di un backslash.

1

PEP-8 dà in realtà esempi di due situazioni simili:

Esempio 1 (sembra più applicabile, dal momento che sta usando with dichiarazioni):

with open('/path/to/some/file/you/want/to/read') as file_1, \ 
    open('/path/to/some/file/being/written', 'w') as file_2: 
    file_2.write(file_1.read()) 

Esempio 2:

class Rectangle(Blob): 

    def __init__(self, width, height, 
       color='black', emphasis=None, highlight=0): 

Sembra come le barre sono un modo permissibile di gestirlo (ma in definitiva non è necessario, se si avvolgono i parametri del file tra parentesi).

3

PEP 8 non è chiaro. Esso menziona solo la dichiarazione with una volta per un'eccezione quando backslashe continuazioni sono a posto:

rovesciare possono ancora essere appropriata, a volte.Ad esempio, lungo, multipla con -statements non può utilizzare continuazione implicita, quindi barre inverse sono accettabili:

with open('/path/to/some/file/you/want/to/read') as file_1, \ 
    open('/path/to/some/file/being/written', 'w') as file_2: 
    file_2.write(file_1.read()) 

Un modo per superare il problema sarebbe infatti effettuare prima chiamata di funzione che restituisce il gestore contesto e poi basta usare che direttamente, come già suggerito nella tua domanda:

file_1 = open('/path/to/some/file/you/want/to/read') 
file_2 = open('/path/to/some/file/being/written', 'w') 

with file_1, file_2: 
    file_2.write(file_1.read()) 

Questo funziona perfettamente (perché l'istruzione with sarà solo chiamare i metodi del gestore contesto, a prescindere da dove proviene), e chiude anche le maniglie in modo corretto .

Tuttavia, questo è esplicitamente consentito nei PEP 8:

manager contesto dovrebbe essere invocata attraverso funzioni o metodi separati ogni volta che fanno qualcosa di diverso da acquisire e rilasciare le risorse. Per esempio:

Sì:

with conn.begin_transaction(): 
    do_stuff_in_transaction(conn) 

No:

with conn: 
    do_stuff_in_transaction(conn) 

Quest'ultimo esempio non fornisce alcuna informazione per indicare che il __enter__ e __exit__ metodi stanno facendo qualcosa di diverso da chiudere la connessione dopo una transazione. Essere espliciti è importante in questo caso.

Così, alla fine, non sembra esserci alcuna vera soluzione che è consentito dal PEP 8. E a quel punto, direi, che è perfettamente bene a “violare it” e andare contro di essa: è solo uno stile guida.

Mentre suggerisce molte buone regole, ci sono anche molte situazioni, in cui semplicemente non ha molto senso seguirle rigorosamente. Direi che il vostro esempio utilizzando barre è difficilmente leggibile, e, probabilmente, si poteva leggere che molto meglio se hai permesso linee più lunghe e appena rotto la linea di una volta al contesto allenatore:

with tempfile.NamedTemporaryFile(prefix='malt_input.conll.', dir=self.working_dir, mode='w', delete=False) as input_file, \ 
    tempfile.NamedTemporaryFile(prefix='malt_output.conll.', dir=self.working_dir, mode='w', delete=False) as output_file: 
    pass 

Sì, potrebbe essere necessario scorrere per questo, ma almeno puoi vedere molto chiaramente cosa sta succedendo.

Un'altra alternativa sarebbe quella di inizializzare in realtà gli oggetti direttamente davanti al with:

malt_input = tempfile.NamedTemporaryFile(prefix='malt_input.conll.', dir=self.working_dir, mode='w', delete=False) 
malt_output = tempfile.NamedTemporaryFile(prefix='malt_output.conll.', dir=self.working_dir, mode='w', delete=False) 
with malt_input as input_file, malt_output as output_file: 
    pass 

Dal momento lo si fa direttamente prima del with, dovrebbe essere un'eccezione alla regola accettabile dal PEP 8 qui. Dopo tutto, migliora la leggibilità, e questo è ciò che conta.

Btw. si noti che un gestore di contesto non può restituire self su __enter__, quindi è ancora necessario utilizzare la sintassi as per assegnare il valore di ritorno del gestore di contesto a una variabile.


Infine, un'altra opzione, che avrebbe funzionato per la vostra situazione particolare, sarebbe quella di avvolgere la chiamata in una funzione separata:

def namedTemp(prefix): 
    return tempfile.NamedTemporaryFile(prefix=prefix, 
     dir=self.working_dir, mode='w', delete=False) 

with namedTemp('malt_input.conll.') as input_file, \ 
    namedTemp('malt_output.conll.') as output_file: 
    pass 

Quindi, fondamentalmente, astratto via tutto, così la dichiarazione with diventa nuovamente leggibile.

+1

Oh, a downvote di uno zelot PEP 8? – poke

+0

PEP8 zelota, bello! – alvas

Problemi correlati