PEP 8 ist nicht allzu klar darüber. Es erwähnt nur die with
-Anweisung einmal für eine Ausnahme, wenn Backslashes Fortsetzungen in Ordnung sind:
Backslashes kann immer noch zeitgerecht sein.Zum Beispiel kann lange, mehrfach mit -Aussagen nicht implizite Fortsetzung verwenden, so Schrägstriche akzeptabel sind:
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())
Ein Weg, das Problem zu überwinden, wäre in der Tat zuerst den Funktionsaufruf, den den Kontext-Manager zurückgibt und dann verwenden nur, dass direkt, wie Sie bereits in Ihrer Frage vorgeschlagen:
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())
das perfekt funktioniert (weil die with
Aussage nur die Methoden des Kontext-Manager nennen, unabhängig davon, woher sie kam), und schließt auch die Griffe richtig .
Dies wird jedoch ausdrücklich in PEP 8 nicht zulässig:
Context Manager sollten durch getrennte Funktionen oder Methoden aufgerufen werden, wenn sie etwas anderes tun, als Ressourcen erwerben und lösen. Zum Beispiel:
Ja:
with conn.begin_transaction():
do_stuff_in_transaction(conn)
No:
with conn:
do_stuff_in_transaction(conn)
Letzteres Beispiel keine Informationen liefern, um anzuzeigen, dass die __enter__
und __exit__
Methoden etwas tun, außer dass die Verbindung geschlossen nach einer Transaktion. Explizit zu sein, ist in diesem Fall wichtig.
Also am Ende, so scheint es keine wirkliche Lösung zu sein, die 8. von PEP erlaubt und an diesem Punkt, ich würde behaupten, dass es völlig in Ordnung ist, „es verletzt“ und geht dagegen: Es ist einfach ein Stil Anleitung.
Während es viele gute Regeln vorschlägt, gibt es auch viele Situationen, in denen es einfach nicht viel Sinn macht, ihnen streng zu folgen. Ich würde behaupten, dass Ihr Beispiel Schrägstriche mit kaum lesbar ist, und man konnte wahrscheinlich liest es viel besser, wenn man längere Linien erlaubt und brach nur die Linie einmal pro Kontext-Manager:
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
Ja, Sie müssen blättern Dafür kann man aber zumindest sehr deutlich sehen, was vor sich geht.
Eine weitere Alternative wäre, um tatsächlich die Objekte direkt vor dem with
zu initialisieren:
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
Da Sie es direkt tun vor dem with
, sollte es eine akzeptable Ausnahme von der PEP 8 Regel hier. Immerhin verbessert es die Lesbarkeit, und darauf kommt es an.
Btw. Beachten Sie, dass ein Kontextmanager möglicherweise self
unter __enter__
nicht zurückgibt. Daher sollten Sie die as
-Syntax verwenden, um den Rückgabewert des Kontextmanagers einer Variablen zuzuweisen.
schließlich eine weitere Option, die für Ihre Situation funktionieren würde, wäre Ihren Anruf in eine separate Funktion zu wickeln:
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
Also im Grunde abstrakt alles weg, so dass die with
Aussage wird wieder lesbar.
Es gibt einen Abschnitt in [PEP8] (https://www.python.org/dev/peps/pep-0008/#maximum-line-length) über maximale Leitungslängen – GP89
[Beyond PEP8] (https: // www.youtube.com/watch?v=wf-BqAjZb8M)! – mkrieger1
mögliche Duplikate von [Wie man eine lange mit der Anweisung in Python bricht] (http://stackoverflow.com/questions/16080049/how-to-break-a-long-with-statement-in-python) – mkrieger1