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.
C'è una sezione in [PEP8] (https://www.python.org/dev/peps/pep-0008/#maximum-line-length) sulla lunghezza massima delle linee – GP89
[Oltre PEP8] (https: // www.youtube.com/watch?v=wf-BqAjZb8M)! – mkrieger1
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