Styling mehrzeiligen Bedingungen in ‚if‘ Aussagen?
-
05-07-2019 - |
Frage
Manchmal breche ich lange Bedingungen in if
s auf mehreren Linien. Die naheliegendste Möglichkeit, dies zu tun ist:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
Ist das nicht sehr, sehr optisch ansprechend, da die Aktion mit den Bedingungen mischt. Es ist jedoch die natürliche Art und Weise richtig Python Einzug von 4 Leerzeichen.
Im Moment bin ich mit:
if ( cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
Aber das ist nicht sehr hübsch. : -)
Können Sie eine alternative Art und Weise empfehlen?
Lösung
Sie brauchen nicht zu 4 Felder auf dem zweiten bedingten Linie zu verwenden. Vielleicht verwenden:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
Auch nicht das Leerzeichen vergessen ist flexibler als Sie vielleicht denken:
if (
cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'
):
do_something
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
Diese beiden sind allerdings ziemlich hässlich.
Möglicherweise ist die Klammern verlieren (der Style Guide schreckt dieses though)?
if cond1 == 'val1' and cond2 == 'val2' and \
cond3 == 'val3' and cond4 == 'val4':
do_something
Das zumindest gibt Ihnen eine gewisse Differenzierung.
Oder auch:
if cond1 == 'val1' and cond2 == 'val2' and \
cond3 == 'val3' and \
cond4 == 'val4':
do_something
Ich glaube, ich ziehe:
if cond1 == 'val1' and \
cond2 == 'val2' and \
cond3 == 'val3' and \
cond4 == 'val4':
do_something
Hier ist der Style Guide , die ( seit 2010) empfiehlt Klammern.
Andere Tipps
Ich habe auf die folgenden in den degenerierten Fall zurückgegriffen, wo es ist einfach und der oder OR ist.
if all( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):
if any( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):
Es rasiert ein paar Zeichen und macht deutlich, dass es keine Subtilität der Bedingung.
Jemand muss Champion Verwendung von vertikalen Leerzeichen hier! :)
if ( cond1 == val1
and cond2 == val2
and cond3 == val3
):
do_stuff()
Das macht jede Bedingung deutlich sichtbar. Es ermöglicht auch sauberen Ausdruck von komplexeren Bedingungen:
if ( cond1 == val1
or
( cond2_1 == val2_1
and cond2_2 >= val2_2
and cond2_3 != bad2_3
)
):
do_more_stuff()
Ja, wir handeln ein wenig vertikalen Immobilien für Klarheit aus. Es lohnt sich meiner Meinung nach.
Hier ist meine sehr persönliche Sicht: lange Bedingungen sind (meiner Meinung nach) einem Code Geruch, Refactoring in eine boolean-Rückkehr Funktion / Methode vorschlägt. Zum Beispiel:
def is_action__required(...):
return (cond1 == 'val1' and cond2 == 'val2'
and cond3 == 'val3' and cond4 == 'val4')
Wenn ich nun einen Weg gefunden, mehrzeiligen Bedingungen gut aussehen zu lassen, würde ich wahrscheinlich mit mir selbst Inhalt finden sie mit und das Refactoring überspringen.
Auf der anderen Seite, mit ihnen meinen ästhetischen Sinne als Anreiz für Refactoring stören.
Meine Schlussfolgerung ist daher, dass mehrere Leitungsbedingungen hässlich aussehen sollen, und das ist ein Anreiz, sie zu vermeiden.
Dies verbessert nicht so viel, aber ...
allCondsAreOK = (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4')
if allCondsAreOK:
do_something
Ich ziehe diesen Stil, wenn ich eine schrecklich große if-Bedingung haben:
if (
expr1
and (expr2 or expr3)
and hasattr(thingy1, '__eq__')
or status=="HappyTimes"
):
do_stuff()
else:
do_other_stuff()
Ich schlage vor, die and
Schlüsselwort in die zweite Zeile bewegt und Einrücken alle Linien Bedingungen mit zwei Räume, in denen statt vier:
if (cond1 == 'val1' and cond2 == 'val2'
and cond3 == 'val3' and cond4 == 'val4'):
do_something
Das ist genau, wie ich dieses Problem in meinem Code zu lösen. viel macht die Bedingung besser lesbar, und die Verringerung der Anzahl der Räume ein Schlüsselwort als das erste Wort in der Zeile mit von Aktion unterscheidet weitere Bedingung.
Es lohnt scheint zitiert PEP 0008 (Python offiziellen Style Guide), da es kommentiert dieses Thema bei bescheidener Länge:
Wenn der bedingte Teil eines
if
-Aussage lang genug ist, zu verlangen, dass es über mehrere Zeilen geschrieben wird, ist es erwähnenswert, dass die Kombination eines zwei Zeichen Schlüsselwort (dhif
), plus ein Leerzeichen, plus eine öffnende Klammer schafft einen natürlichen 4-space Gedankenstrich für die nachfolgenden Zeilen der mehrzeiligen bedingt. Dies kann einen visuellen Konflikt mit der gegliederten Reihe von Code innerhalb desif
-Anweisung verschachtelt produzieren, die auch in der Natur zu 4 Leerzeichen eingerückt sein würde. Dieser PEP nimmt keine explizite Position, wie (oder ob) weiter visuell die solche Zeilen aus der verschachtelten Suite innerhalb desif
-Aussage zu unterscheiden. Akzeptable Optionen in dieser Situation umfassen, sind aber nicht beschränkt auf:# No extra indentation. if (this_is_one_thing and that_is_another_thing): do_something() # Add a comment, which will provide some distinction in editors # supporting syntax highlighting. if (this_is_one_thing and that_is_another_thing): # Since both conditions are true, we can frobnicate. do_something() # Add some extra indentation on the conditional continuation line. if (this_is_one_thing and that_is_another_thing): do_something()
Beachten Sie die „nicht auf“ in dem Zitat oben; neben den Ansätzen in dem Style Guide vorgeschlagen, sind auch akzeptabel einige von denen in anderen Antworten auf diese Frage vorgeschlagen.
Hier ist, was ich tue, denken Sie daran, dass „alle“ und „any“ eine iterable akzeptiert, so dass ich nur einen langen Zustand in einer Liste und lassen Sie „alle“ die Arbeit machen.
condition = [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4']
if all(condition):
do_something
Ich bin überrascht, nicht meine bevorzugte Lösung, um zu sehen,
if (cond1 == 'val1' and cond2 == 'val2'
and cond3 == 'val3' and cond4 == 'val4'):
do_something
Da and
ein Schlüsselwort ist, es von meinem Editor hervorgehoben wird, und sieht ausreichend verschieden von dem do_something darunter.
Ich persönlich mag if-Anweisungen Bedeutung zu lange hinzuzufügen. Ich würde durch den Code suchen ein geeignetes Beispiel zu finden, aber hier ist das erste Beispiel, das in dem Sinne kommt. Lassen Sie sich sagen, ich zufällig in eine schrullige Logik laufen, wo ich eine bestimmte Seite in Abhängigkeit von vielen Variablen angezeigt werden soll
Englisch: „Wenn der angemeldete Benutzer keinen Administrator Lehrer, sondern ist nur ein ganz normaler Lehrer, und ist kein Student selbst ...“
if not user.isAdmin() and user.isTeacher() and not user.isStudent():
doSomething()
Sicher könnte dies gut aussehen, aber die, wenn Aussagen zu lesen ist eine Menge Arbeit. Wie wäre es wir die Logik Label zuweisen, die Sinn macht. Das „Label“ ist eigentlich der Variablenname:
displayTeacherPanel = not user.isAdmin() and user.isTeacher() and not user.isStudent()
if displayTeacherPanel:
showTeacherPanel()
Das mag albern, aber man könnte noch eine weitere Bedingung, wo Sie nur, wenn Sie ein anderes Element angezeigt werden soll, und nur dann, wenn Sie zum Lehrer-Panel angezeigt wird oder wenn der Benutzer den Zugriff auf diese anderen spezifischen Panel standardmäßig hat:
if displayTeacherPanel or user.canSeeSpecialPanel():
showSpecialPanel()
Versuchen Sie, die obige Bedingung zu schreiben, ohne Variablen mit Ihrer Logik zu speichern und beschriften, und nicht nur Sie am Ende mit einer sehr chaotisch, schwer zu lesen logischen Aussage, aber Sie haben auch selbst nur wiederholt. Zwar gibt es vernünftige Ausnahmen sind, erinnern. Sie not Repeat Yourself (DRY)
„Alle“ und „any“ sind schön für die vielen Bedingungen gleichen Typs Fall. Aber sie wertet immer alle Bedingungen. Wie in diesem Beispiel gezeigt:
def c1():
print " Executed c1"
return False
def c2():
print " Executed c2"
return False
print "simple and (aborts early!)"
if c1() and c2():
pass
print
print "all (executes all :( )"
if all((c1(),c2())):
pass
print
(Ich habe leicht die Kennungen als feste Breite Namen geändert ist nicht repräsentativ für echte Code - zumindest nicht wirklich Code, den ich begegne -. Und werde ein Beispiel der Lesbarkeit hinwegtäuschen)
if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4"):
do_something
Das funktioniert gut für „und“ und „oder“ (es ist wichtig, dass sie zum ersten Mal in der zweiten Zeile sind), aber viel weniger für andere lange Bedingungen. Glücklicherweise scheinen die erstere der häufigere Fall, während die letzteren oft leicht mit einer temporären Variablen neu geschrieben werden. (Es ist in der Regel nicht schwer, aber es kann schwierig oder viel weniger offensichtlich / lesbar sein, das Kurzschließen „und“ / „oder“ zu erhalten, wenn neu zu schreiben.)
Da fand ich diese Frage von eine Blog-Post über C ++ , werde ich schließen, dass mein C ++ Stil ist identisch:
if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4") {
do_something
}
Das Hinzufügen was @krawyoti sagte ... Lange Bedingungen riechen, weil sie schwer zu lesen und schwer zu verstehen sind. Mit Hilfe einer Funktion oder eine Variable macht den Code klarer. In Python, ziehe ich es vertikalen Raum zu verwenden, schließt Klammer, und legen Sie die logischen Operatoren am Anfang jeder Zeile, so dass die Ausdrücke wie „schwebenden“ nicht aussehen.
conditions_met = (
cond1 == 'val1'
and cond2 == 'val2'
and cond3 == 'val3'
and cond4 == 'val4'
)
if conditions_met:
do_something
Wenn die Bedingungen müssen mehr ausgewertet werden als einmal, wie in einer while
Schleife, dann mit einer lokalen Funktion am besten ist.
Schlicht und einfach, auch geht PEP8 Kontrollen:
if (
cond1 and
cond2
):
print("Hello World!")
In der letzten Zeit habe ich gewesen, die all
und any
Funktionen bevorzugen, da ich selten mische Und und Oder Vergleiche dies funktioniert gut und hat den zusätzlichen Vorteil der erlöschenden Frühe mit Generatoren Verständnis:
if all([
cond1,
cond2,
]):
print("Hello World!")
Denken Sie daran, in einem einzigen iterable passieren! Passing in N-Argumente ist nicht korrekt.
Hinweis: any
ist wie viele or
Vergleiche, ist all
wie viele and
Vergleiche
Dies kombiniert gut mit Generator Comprehensions, zum Beispiel:
# Check if every string in a list contains a substring:
my_list = [
'a substring is like a string',
'another substring'
]
if all('substring' in item for item in my_list):
print("Hello World!")
# or
if all(
'substring' in item
for item in my_list
):
print("Hello World!")
Mehr an: Generator Verständnis
Was ist, wenn wir nur eine zusätzliche Leerzeile zwischen dem Zustand und dem Körper einsetzen und den Rest in der kanonischen Weise tun?
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
P. S. Ich benutze Tabs immer, keine Leerzeichen; Ich kann nicht die Feinabstimmung ...
Nur ein paar andere zufälligen Ideen für Vollständigkeit willen. Wenn sie für Sie arbeiten, sie verwenden. Ansonsten sind Sie wahrscheinlich besser dran, etwas anderes zu versuchen.
Sie können auch dies mit einem Wörterbuch:
>>> x = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> y = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> x == y
True
Diese Option ist komplizierter, aber Sie können auch finden es nützlich:
class Klass(object):
def __init__(self, some_vars):
#initialize conditions here
def __nonzero__(self):
return (self.cond1 == 'val1' and self.cond2 == 'val2' and
self.cond3 == 'val3' and self.cond4 == 'val4')
foo = Klass()
if foo:
print "foo is true!"
else:
print "foo is false!"
Keine Ahnung, ob das funktioniert für Sie, aber es ist eine andere Option zu prüfen. Hier ist eine weitere Möglichkeit:
class Klass(object):
def __init__(self):
#initialize conditions here
def __eq__(self):
return (self.cond1 == 'val1' and self.cond2 == 'val2' and
self.cond3 == 'val3' and self.cond4 == 'val4')
x = Klass(some_values)
y = Klass(some_other_values)
if x == y:
print 'x == y'
else:
print 'x!=y'
Die letzten beiden habe ich nicht getestet, aber die Konzepte sollten genug sein, um Sie gehen, wenn das ist, was Sie mit gehen wollen.
(Und für die Aufzeichnung, wenn dies nur eine einmalige Sache ist, sind Sie wahrscheinlich nur besser mit der Methode, die Sie zunächst dargestellt. Wenn Sie den Vergleich in vielen Orten tun, diese Methoden Lesbarkeit verbessern können genug, um Sie nicht zu machen über die Tatsache, so schlecht fühlen, dass sie Art von hacky sind.)
Was ich in der Regel tun, ist:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'
):
do_something
auf diese Weise der schließende Klammer und Doppelpunkt markiert visuell das Ende unseres Zustandes.
Ich habe kämpfen, um eine anständige Art und Weise zu finden, dies auch zu tun, so kam ich nur mit einer Idee (kein Allheilmittel, da dies in erster Linie eine Frage des Geschmacks ist).
if bool(condition1 and
condition2 and
...
conditionN):
foo()
bar()
Ich finde einige Verdienste in dieser Lösung im Vergleich zu anderen, die ich gesehen habe, nämlich, man bekommt genau einen zusätzlichen 4 Räume der Vertiefung (Bool), alle Bedingungen, die die vertikal ausgerichtet ist, und der Körper der if-Anweisung kann in einer klaren (Ish) Art und Weise eingerückt werden. Dies hält auch die Vorteile der Kurzauswertung von Booleschen Operatoren, aber natürlich fügt den Overhead eines Funktionsaufruf, der im Grunde nichts tut. Sie könnten (gültig) argumentieren, dass jede Funktion sein Arguments Rückkehr statt Bool hier verwendet werden könnte, aber wie ich schon sagte, es ist nur eine Idee, und es ist letztlich eine Frage des Geschmacks.
Lustig genug, wie ich dies und das Denken über das „Problem“ schrieb, kam ich mit noch ein anderes Idee, die den Overhead eines Funktionsaufrufs entfernt. Warum nicht zeigen, dass wir im Begriff sind eine komplexe Bedingung eingeben, indem Sie zusätzliche Paare von Klammern? Sprich: 2 mehr, einen schönen 2 Raum Einzug des Unter Bedingungen in Bezug auf den Körper der if-Anweisung zu geben. Beispiel:
if (((foo and
bar and
frob and
ninja_bear))):
do_stuff()
ich mag das, weil, wenn man es betrachtet, eine Glocke immediatelly im Kopf klingelt sagen „Hey, es ist eine komplexe Sache hier los ist!“ . Ja, ich weiß, dass Klammern Lesbarkeit nicht helfen, aber diese Bedingungen sollten selten genug erscheinen, und wenn sie auftauchen tun, Sie gehen zu müssen, sie carefuly sowieso stoppen und lesen (weil sie Komplex ).
Wie auch immer, nur zwei weitere Vorschläge, die ich hier nicht gesehen haben. Hoffe, das hilft jemand:)
Sie könnten es in zwei Linien aufgeteilt
total = cond1 == 'val' and cond2 == 'val2' and cond3 == 'val3' and cond4 == val4
if total:
do_something()
oder sogar unter einer Bedingung zu einem Zeitpunkt hinzuzufügen. Auf diese Weise, zumindest ist es die Unordnung aus dem if
trennt.
Ich weiß, dieser Thread ist alt, aber ich habe einige Python 2.7 Code und PyCharm (4.5) noch beschwert sich über diesen Fall:
if foo is not None:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
# some comment about do_something
do_something
Auch bei der PEP8 Warnung „visuell eingekerbten Linie mit dem gleichen Gedankenstrich als nächste logische Linie“, der eigentliche Code ist völlig in Ordnung? Es ist nicht "over-Einrücken?"
... es gibt Zeiten, ich Python will etwas die Kugel haben würde und nur mit geschweiften Klammern weg. Ich frage mich, wie viele Fehler wurden wegen der versehentlichen Fehl Einzug über die Jahre versehentlich eingeführt worden ...
Alle Befragten, die auch Multi-conditionals für das zur Verfügung stellen, wenn Aussage genauso hässlich wie das Problem dargestellt. Sie lösen dieses Problem nicht durch das gleiche tun ..
Auch die PEP 0008 Antwort ist abstoßend.
Hier ist ein weit lesbarer Ansatz
condition = random.randint(0, 100) # to demonstrate
anti_conditions = [42, 67, 12]
if condition not in anti_conditions:
pass
Wollen Sie mir meine Worte essen? Überzeugen Sie mich Sie brauchen Multi-conditionals und ich werde buchstäblich drucken diese und essen es für Ihre Unterhaltung.
Ich denke, @ zkanda-Lösung mit einem kleinen Twist gut wäre. Wenn Sie Ihre Bedingungen und Werte in ihren eigenen jeweiligen Listen haben, könnten Sie eine Liste Verständnis verwenden Sie den Vergleich zu tun, die Dinge ein wenig allgemein für das Hinzufügen Zustand / Wert-Paare machen würde.
conditions = [1, 2, 3, 4]
values = [1, 2, 3, 4]
if all([c==v for c, v in zip(conditions, values)]):
# do something
Wenn ich eine Erklärung zu hart Code wie dieser wollte, würde ich es so schreibe für Lesbarkeit:
if (condition1==value1) and (condition2==value2) and \
(condition3==value3) and (condition4==value4):
Und eine andere Lösung zu werfen dort aus mit einem iand
Operator
proceed = True
for c, v in zip(conditions, values):
proceed &= c==v
if proceed:
# do something
Packen Sie Ihre Bedingungen in eine Liste, dann smth tun. wie:
if False not in Conditions:
do_something
Ich finde, dass, wenn ich lange Bedingungen habe, habe ich oft einen kurzen Code Körper. In diesem Fall habe ich einfach doppelt Einzug der Körper, also:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
if cond1 == 'val1' and \
cond2 == 'val2' and \
cond3 == 'val3' and \
cond4 == 'val4':
do_something
oder, wenn dies deutlicher:
if cond1 == 'val1'\
and cond2 == 'val2'\
and cond3 == 'val3'\
and cond4 == 'val4':
do_something
Es gibt keinen Grund indent ein Vielfaches von 4 ist in diesem Fall sein sollte, z.B. siehe "Aligned mit Öffnungstrennzeichen":
Hier ist ein weiterer Ansatz:
cond_list = ['cond1 == "val1"','cond2=="val2"','cond3=="val3"','cond4=="val4"']
if all([eval(i) for i in cond_list]):
do something
Dies macht es auch einfach, ohne die if-Anweisung eine andere Bedingung leicht hinzufügen, indem Sie einfach eine andere Bedingung zur Liste hinzugefügt wird:
cond_list.append('cond5=="val5"')
ich in der Regel verwenden:
if ((cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4')):
do_something()
Wenn unsere wenn & eine andere Bedingung mehrere Anweisung innerhalb davon auszuführen hat, als wir wie unten schreiben. Jedes wenn wir haben, wenn anderes Beispiel mit einer Aussage im Innern.
Danke es für mich arbeiten.
#!/usr/bin/python
import sys
numberOfArgument =len(sys.argv)
weblogic_username =''
weblogic_password = ''
weblogic_admin_server_host =''
weblogic_admin_server_port =''
if numberOfArgument == 5:
weblogic_username = sys.argv[1]
weblogic_password = sys.argv[2]
weblogic_admin_server_host =sys.argv[3]
weblogic_admin_server_port=sys.argv[4]
elif numberOfArgument <5:
print " weblogic UserName, weblogic Password and weblogic host details are Mandatory like, defalutUser, passwordForDefaultUser, t3s://server.domainname:7001 ."
weblogic_username = raw_input("Enter Weblogic user Name")
weblogic_password = raw_input('Enter Weblogic user Password')
weblogic_admin_server_host = raw_input('Enter Weblogic admin host ')
weblogic_admin_server_port = raw_input('Enter Weblogic admin port')
#enfelif
#endIf