2015-08-14 3 views
6

Was der pythonic Weg PEP-8-ify wie mit Aussage:80 Zeichen Rand für lange mit Aussage halten?

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 

ich dies tun könnte, aber da das tempfile i/o ist nicht mit der with Aussage, tut es automatisch nach dem mit ? Ist das pythonic ?:

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 

Oder ich könnte verwenden Schrägstriche:

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 

Aber ist das PEP8 Comply-fähig? Ist das Python?

+1

Es gibt einen Abschnitt in [PEP8] (https://www.python.org/dev/peps/pep-0008/#maximum-line-length) über maximale Leitungslängen – GP89

+1

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

+1

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

Antwort

3

PEP 0008 does say it's ok Backslashes für eine with Linie zu verwenden.

Backslashes kann manchmal noch angebracht sein. Zum Beispiel können lange, mehrere mit-Anweisungen keine implizite Fortsetzung verwenden, daher sind Backslashes akzeptabel.

Obwohl es empfiehlt sie eingerückt werden, so sollten Sie Ihre Zeile wie folgt sein:

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 

Es ist ratsam, Sie halten es eine deutlich unterschiedliche Menge an Speicherplatz auf den folgenden Code-Block eingerückt, so ist es übersichtlicher wo die mit Linie endet und der Block beginnt.

aber Sie nicht wirklich Notwendigkeit Schrägstriche zu verwenden, wenn Sie die Parameter in Klammern ein

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 

, die auf Ihrem genauen Satz Anordnung natürlich und Ihre Meilenzahl kann, ob mit einer Klammer variieren abhängig ist am Ende einer Zeile ist besser als ein Backslash.

1

PEP-8 tatsächlich gibt Beispiele für zwei ähnliche Situationen:

Beispiel 1 (sieht sehr anwendbar, da es with Aussagen ist mit):

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()) 

Beispiel 2:

class Rectangle(Blob): 

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

Es sieht Wie Schrägstriche sind eine erlaubte Möglichkeit, dies zu handhaben (aber letztlich unnötig, wenn Sie Ihre Dateiparameter in Klammern umbrechen).

3

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.

+1

Oh, a von einem PEP 8 Zelot? – poke

+0

PEP8 Zelot, netter! – alvas

Verwandte Themen