Frage

Manchmal breche ich lange Bedingungen in ifs 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?

War es hilfreich?

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 (dh if), 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 des if -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 des if -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":

http: //google-styleguide.googlecode. com / svn / trunk / pyguide.html? showone = Indentation # Einrückungen

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top