Voorwaarden met meerdere regels opmaken in ‘if’-statements?

Soms breek ik lange voorwaarden in ifs op meerdere regels. De meest voor de hand liggende manier om dit te doen is:

 if (cond1 == 'val1' and cond2 == 'val2' and
      cond3 == 'val3' and cond4 == 'val4'):
      do_something

Is visueel niet erg aantrekkelijk, omdat de actie zich vermengt met de omstandigheden. Het is echter de natuurlijke manier om de juiste Python-inspringing van 4 spaties te gebruiken.

Voorlopig gebruik ik:

 if (    cond1 == 'val1' and cond2 == 'val2' and
          cond3 == 'val3' and cond4 == 'val4'):
      do_something

Maar dit is niet erg mooi. 🙂

Kunt u een alternatieve manier aanbevelen?


Antwoord 1, autoriteit 100%

Je hoeft geen 4 spaties te gebruiken op je tweede voorwaardelijke regel. Gebruik misschien:

if (cond1 == 'val1' and cond2 == 'val2' and 
       cond3 == 'val3' and cond4 == 'val4'):
    do_something

Vergeet ook niet dat de witruimte flexibeler is dan je zou 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

Beide zijn echter behoorlijk lelijk.

Misschien verliest u de haakjes (de Stijlgidsontmoedigt dit echter)?

if cond1 == 'val1' and cond2 == 'val2' and \
   cond3 == 'val3' and cond4 == 'val4':
    do_something

Dit geeft je tenminste wat differentiatie.

of zelfs:

if cond1 == 'val1' and cond2 == 'val2' and \
                       cond3 == 'val3' and \
                       cond4 == 'val4':
    do_something

Ik denk dat ik de voorkeur heb:

if cond1 == 'val1' and \
   cond2 == 'val2' and \
   cond3 == 'val3' and \
   cond4 == 'val4':
    do_something

Hier is de stijl gids , die ( Sinds 2010) beveelt u aan beugels te gebruiken.


Antwoord 2, Autoriteit 15%

Ik heb toevlucht genomen tot het volgende in het gedegenereerde geval waar het eenvoudig en ofs of of’s is.

if all( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):
if any( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):

Het scheert een paar tekens en maakt duidelijk dat er geen subtiliteit is op de voorwaarde.


Antwoord 3, Autoriteit 7%

Iemand heeft hier te kamperen gebruik van verticale witruimte! 🙂

if (     cond1 == val1
     and cond2 == val2
     and cond3 == val3
   ):
    do_stuff()

Dit maakt elke toestand duidelijk zichtbaar. Het staat ook schonere expressie van complexere omstandigheden toe:

if (    cond1 == val1
     or 
        (     cond2_1 == val2_1
          and cond2_2 >= val2_2
          and cond2_3 != bad2_3
        )
   ):
    do_more_stuff()

Ja, we zijn een beetje verticaal onroerend goed voor de duidelijkheid. Zeker de moeite waard imo.


Antwoord 4, Autoriteit 4%

Ik geef de voorkeur aan deze stijl als ik een vreselijk grote als-conditie heb:

if (
    expr1
    and (expr2 or expr3)
    and hasattr(thingy1, '__eq__')
    or status=="HappyTimes"
):
    do_stuff()
else:
    do_other_stuff()

Antwoord 5, Autoriteit 3%

Hier is mijn zeer persoonlijke take: Long Conditions zijn (in mijn mening) een codeur die suggereert dat het refactoreren in een Boolean-retourfunctie / -methode. Bijvoorbeeld:

def is_action__required(...):
    return (cond1 == 'val1' and cond2 == 'val2'
            and cond3 == 'val3' and cond4 == 'val4')

Nu, als ik een manier vond om meerdere regel omstandigheden goed uit te laten zien, zou ik waarschijnlijk mezelf tevreden vinden met het hebben van ze en de refactoring overslaan.

Aan de andere kant, met het perturberen van mijn esthetische sense fungeert als een stimulans voor het refactoren.

Mijn conclusie, daarom is dat meerdere regelvoorwaarden lelijk uitzien en dit is een stimulans om ze te vermijden.


Antwoord 6, Autoriteit 3%

Dit verbetert niet zo veel, maar …

allCondsAreOK = (cond1 == 'val1' and cond2 == 'val2' and
                 cond3 == 'val3' and cond4 == 'val4')
if allCondsAreOK:
   do_something

Antwoord 7, Autoriteit 2%

Ik stel voor om de andtrefwoord naar de tweede regel te verplaatsen en alle lijnen met omstandigheden met twee ruimtes in plaats van vier:

if (cond1 == 'val1' and cond2 == 'val2'
  and cond3 == 'val3' and cond4 == 'val4'):
    do_something

Dit is precies hoe ik dit probleem in mijn code oplost. Het hebben van een sleutelwoord als het eerste woord in de lijn maakt de voorwaarde een stuk leesbaarder en het verminderen van het aantal ruimtes, onderscheidt verder voorwaarde uit actie.


Antwoord 8, Autoriteit 2%

Het lijkt de moeite waard te citeren PEP 0008 (Python’s Official Style Guide), Aangezien het opmerkingen van dit probleem bij bescheiden lengte:

Wanneer het voorwaardelijke deel van een if-statement lang genoeg is om te eisen dat het over meerdere lijnen wordt geschreven, is het vermeldenswaard dat de combinatie van een trefwoord van twee tekens (dwz if), plus een enkele ruimte, plus een opening van haakjes creëert een natuurlijke 4-ruimte-streepje voor de daaropvolgende lijnen van de multiline-voorwaardelijke. Dit kan een visueel conflict produceren met de ingesprongen reeks van de code genest in de if-Statement, die ook natuurlijk inspringend zou zijn tot 4 spaties. Deze PEP neemt geen expliciete positie op hoe (of of) deze voorwaardelijke lijnen verder visueel van de geneste suite in de if-statement. Aanvaardbare opties in deze situatie omvatten, maar zijn niet beperkt tot:

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

Let op de “niet beperkt tot” in de bovenstaande offerte; Naast de voorgestelde benaderingen in de stijlgids, suggereerden sommige van degenen die in andere antwoorden op deze vraag zijn voorgesteld, ook aanvaardbaar.


Antwoord 9

Hier is wat ik doe, onthoud dat “alles” en “elk” een iezak accepteert, dus ik plaats gewoon een lange conditie in een lijst en laat “alles” het werk doen.

condition = [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4']
if all(condition):
   do_something

Antwoord 10

Toevoegen aan wat @krawyoti zei … lange omstandigheden ruiken omdat ze moeilijk te lezen en moeilijk te begrijpen zijn. Met behulp van een functie of een variabele maakt de code duidelijker. In Python, ik gebruik de voorkeur om een ​​verticale ruimte te gebruiken, haakjes om te vechten en de logische operators aan het begin van elke regel te plaatsen, zodat de uitdrukkingen er niet uitzien als “drijvend”.

conditions_met = (
    cond1 == 'val1' 
    and cond2 == 'val2' 
    and cond3 == 'val3' 
    and cond4 == 'val4'
    )
if conditions_met:
    do_something

Als de voorwaarden meer dan één keer moeten worden geëvalueerd, zoals in een whilelus, dan het gebruik van een lokale functie het beste is.


Antwoord 11

Ik ben verrast om mijn voorkeursoplossing niet te zien,

if (cond1 == 'val1' and cond2 == 'val2'
    and cond3 == 'val3' and cond4 == 'val4'):
    do_something

Sinds andis het een sleutelwoord, het wordt gemarkeerd door mijn editor en ziet er voldoende anders uit van de Do_Something hieronder.


Antwoord 12

Persoonlijk voeg ik graag betekenis toe aan lange if-statements. Ik zou door de code moeten zoeken om een geschikt voorbeeld te vinden, maar dit is het eerste voorbeeld dat in me opkomt: laten we zeggen dat ik toevallig een eigenaardige logica tegenkom waarbij ik een bepaalde pagina wil weergeven, afhankelijk van veel variabelen.

Nederlands: “Als de ingelogde gebruiker GEEN administrator-leraar is, maar gewoon een gewone leraar is en zelf geen student is…”

if not user.isAdmin() and user.isTeacher() and not user.isStudent():
    doSomething()

Natuurlijk ziet dit er misschien goed uit, maar het lezen van die if-statements is veel werk. Wat als we de logica toewijzen aan een label dat logisch is. Het “label” is eigenlijk de naam van de variabele:

displayTeacherPanel = not user.isAdmin() and user.isTeacher() and not user.isStudent()
if displayTeacherPanel:
    showTeacherPanel()

Dit lijkt misschien gek, maar je hebt misschien nog een andere voorwaarde waarbij je ALLEEN een ander item wilt weergeven als, en alleen als, je het docentenpaneel weergeeft OF als de gebruiker standaard toegang heeft tot dat andere specifieke paneel:

if displayTeacherPanel or user.canSeeSpecialPanel():
    showSpecialPanel()

Probeer de bovenstaande voorwaarde te schrijven zonder variabelen te gebruiken om je logica op te slaan en te labelen, en je krijgt niet alleen een erg rommelige, moeilijk te lezen logische verklaring, maar je herhaalt jezelf ook gewoon. Hoewel er redelijke uitzonderingen zijn, onthoud: Don’t Repeat Yourself (DRY).


Antwoord 13

Eenvoudig, slaagt ook voor pep8-controles:

if (
    cond1 and
    cond2
):
    print("Hello World!")

De laatste tijd heb ik de voorkeur gegeven aan de functies allen any, aangezien ik zelden And en Or-vergelijkingen mix, dit werkt goed, en heeft als bijkomend voordeel dat het vroegtijdig faalt met begrip van generatoren:

if all([
    cond1,
    cond2,
]):
    print("Hello World!")

Vergeet niet om in één iterable door te geven! N-argumenten doorgeven is niet correct.

Opmerking: anyis als veel orvergelijkingen, allis als veel andvergelijkingen.


Dit combineert mooi met begrip van generatoren, bijvoorbeeld:

# 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!")

Meer over: generatorbegrip


Antwoord 14

“alle” en “elke” zijn leuk voor de vele omstandigheden van hetzelfde type geval. MAAR ze evalueren altijd alle voorwaarden. Zoals in dit voorbeeld:

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

Antwoord 15

(Ik heb de ID’s licht gewijzigd, omdat namen met vaste breedte niet representatief zijn voor echte code – althans niet echte code die ik tegenkom – en zal de leesbaarheid van een voorbeeld van een voorbeeld zijn.)

if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4"):
    do_something

Dit werkt goed voor “en” en “of” (het is belangrijk dat ze eerst op de tweede regel zijn), maar veel minder voor andere lange omstandigheden. Gelukkig lijkt de eerste de meest voorkomende zaak te zijn, terwijl de laatste vaak gemakkelijk worden herschreven met een tijdelijke variabele. (Het is meestal niet moeilijk, maar het kan moeilijk of veel minder voor de hand liggend / leesbaar zijn om het kortsluiting van “en” / “of” te behouden bij het herschrijven.)

Sinds ik deze vraag vond van Uw blogpost over C++ , ik neem me op dat mijn C++ -stijl identiek is:

if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4") {
    do_something
}

Antwoord 16

Wat als we alleen een extra lege lijn tussen de conditie en het lichaam plaatsen en de rest op de Canonical Way doen?

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'):
    do_something

P.S. Ik gebruik altijd tabbladen, geen spaties; Ik kan niet fijn maken …


Antwoord 17

Wat ik gewoonlijk doe, is:

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'
   ):
    do_something

Op deze manier markeren de sluitingsbeugel en dikke darm visueel het einde van onze toestand.


Antwoord 18

Alle respondenten die ook multi-conditionals leveren voor de IF-verklaring is net zo lelijk als het probleem gepresenteerd. Je lost dit probleem niet op door hetzelfde te doen.

Zelfs het PEP 0008-antwoord is afstotelijk.

Hier is een veel meer leesbare aanpak

condition = random.randint(0, 100) # to demonstrate
anti_conditions = [42, 67, 12]
if condition not in anti_conditions:
    pass

Wil je dat ik mijn woorden eet? Overtuig me dat je multi-conditionals nodig hebt en ik print dit letterlijk en eet het op voor je amusement.


Antwoord 19

Ik denk dat de oplossing van @ Zkanda goed zou zijn met een kleine draai. Als u uw voorwaarden en waarden in hun eigen respectievelijke lijsten had, kunt u een lijstbegrip gebruiken om de vergelijking te doen, wat dingen een beetje meer generaal zou maken voor het toevoegen van conditie / waardeparen.

conditions = [1, 2, 3, 4]
values = [1, 2, 3, 4]
if all([c==v for c, v in zip(conditions, values)]):
    # do something

Als ik deed hardcodes een verklaring als deze, zou ik het zo schrijven voor leesbaarheid:

if (condition1==value1) and (condition2==value2) and \
   (condition3==value3) and (condition4==value4):

En gewoon om een ​​andere oplossing te gooien met een iandOperator :

proceed = True
for c, v in zip(conditions, values):
    proceed &= c==v
if proceed:
    # do something

Antwoord 20

Slechts een paar andere willekeurige ideeën voor de volledigheid. Als ze voor u werken, gebruik ze dan. Anders ben je waarschijnlijk beter iets anders uit.

U kunt dit ook doen met een woordenboek:

>>> x = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> y = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> x == y
True

Deze optie is ingewikkelder, maar u kunt het ook nuttig vinden:

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!"

Dunno als dat voor u werkt, maar het is een andere optie om te overwegen. Dit is nog een manier:

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'

De laatste twee die ik niet heb getest, maar de concepten moeten genoeg zijn om je naartoe te laten gaan als dat is waar je mee wilt.

(En voor de goede orde, als dit slechts een eenmalig iets is, kunt u waarschijnlijk beter de methode gebruiken die u in eerste instantie presenteerde. Als u de vergelijking op veel plaatsen uitvoert, kunnen deze methoden de leesbaarheid verbeteren genoeg om je niet zo slecht te laten voelen over het feit dat ze een beetje hacky zijn.)


Antwoord 21

Ik heb ook moeite gehad om een fatsoenlijke manier te vinden om dit te doen, dus ik kwam net op een idee (geen wondermiddel, aangezien dit vooral een kwestie van smaak is).

if bool(condition1 and
        condition2 and
        ...
        conditionN):
    foo()
    bar()

Ik vind een paar voordelen in deze oplossing in vergelijking met andere die ik heb gezien, namelijk, je krijgt precies 4 extra spaties voor inspringing (bool), waardoor alle voorwaarden verticaal kunnen worden uitgelijnd, en de hoofdtekst van de if-instructie kan op een duidelijke (achtige) manier worden ingesprongen. Dit behoudt ook de voordelen van kortsluitingsevaluatie van booleaanse operatoren, maar voegt natuurlijk de overhead toe van een functieaanroep die in feite niets doet. Je zou (geldig) kunnen stellen dat elke functie die zijn argument retourneert hier kan worden gebruikt in plaats van bool, maar zoals ik al zei, het is maar een idee en het is uiteindelijk een kwestie van smaak.

Grappig genoeg, terwijl ik dit aan het schrijven was en over het “probleem” nadacht, kwam ik op nog een anderidee, dat de overhead van een functieaanroep verwijdert. Waarom geven we niet aan dat we op het punt staan een complexe voorwaarde in te voeren door extra paar haakjes te gebruiken? Zeg, nog 2, om een mooi 2 spatie-inspringing van de subvoorwaarden te geven ten opzichte van de hoofdtekst van de if-instructie. Voorbeeld:

if (((foo and
      bar and
      frob and
      ninja_bear))):
    do_stuff()

Ik vind dit zo leuk, want als je ernaar kijkt, rinkelt een bel onmiddellijke ringen in je hoofd en zegt “Hé, er is een complex ding hier!” . Ja, ik weet dat haakjes geen leesbaarheid helpen, maar deze voorwaarden zouden zelden genoeg moeten lijken, en wanneer ze eraan komen, moet je ze stoppen en ze toch voorzichtig zijn (omdat ze Complex ).

Hoe dan ook, slechts twee meer voorstellen die ik hier niet heb gezien. Ik hoop dat dit iemand helpt:)


Antwoord 22

U kunt het in twee regels delen

total = cond1 == 'val' and cond2 == 'val2' and cond3 == 'val3' and cond4 == val4
if total:
    do_something()

of voeg zelfs één voorwaarde tegelijk toe. Op die manier scheidt het tenminste de rommel van de if.


Antwoord 23

Ik weet dat deze thread oud is, maar ik heb wat Python 2.7-code en Pycharm (4.5) klacht nog steeds over deze zaak:

if foo is not None:
    if (cond1 == 'val1' and cond2 == 'val2' and
        cond3 == 'val3' and cond4 == 'val4'):
            # some comment about do_something
            do_something

Zelfs met de PEP8-waarschuwing “Visueel ingesprongen lijn met hetzelfde streepje als volgende logische lijn”, is de daadwerkelijke code helemaal ok? Het is niet “overonderstaand?”

… er zijn tijden, ik wou dat Python de kogel zou hebben en gewoon met krullende beugels is gegaan. Ik vraag me af hoeveel insecten per ongeluk in de loop der jaren zijn geïntroduceerd als gevolg van accidentele misleiding …


Antwoord 24

Pak uw omstandigheden in een lijst in en doe dan SMTH. Zoals:

if False not in Conditions:
    do_something

Antwoord 25

Ik merk dat wanneer ik lange voorwaarden heb, ik vaak een korte code heb. In dat geval laat ik de body dubbel inspringen, dus:

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'):
        do_something

Antwoord 26

 if cond1 == 'val1' and \
     cond2 == 'val2' and \
     cond3 == 'val3' and \
     cond4 == 'val4':
      do_something

of als dit duidelijker is:

 if cond1 == 'val1'\
     and cond2 == 'val2'\
     and cond3 == 'val3'\
     and cond4 == 'val4':
      do_something

Er is geen reden waarom inspringen in dit geval een veelvoud van 4 zou moeten zijn, bijv. zie “Uitgelijnd met openingsscheidingsteken”:

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


Antwoord 27

Hier is een andere benadering:

cond_list = ['cond1 == "val1"','cond2=="val2"','cond3=="val3"','cond4=="val4"']
if all([eval(i) for i in cond_list]):
 do something

Dit maakt het ook gemakkelijk om eenvoudig een andere voorwaarde toe te voegen zonder de if-instructie te wijzigen door simpelweg een andere voorwaarde aan de lijst toe te voegen:

cond_list.append('cond5=="val5"')

Antwoord 28

Ik gebruik meestal:

if ((cond1 == 'val1' and cond2 == 'val2' and
     cond3 == 'val3' and cond4 == 'val4')):
    do_something()

Antwoord 29

als onze if & een else-voorwaarde moet meerdere instructies erin uitvoeren dan we kunnen schrijven zoals hieronder.
Elke als we een ander voorbeeld hebben met één statement erin.

Bedankt, het werkt voor mij.

#!/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

Antwoord 30

Neem me niet kwalijk, maar het gebeurt dat ik niet zo goed op de hoogte ben van #Python als iemand van jullie hier, maar het gebeurt dat ik iets soortgelijks heb gevonden bij het scripten van mijn eigen objecten in een 3D BIM-modellering, dus ik zal het aanpassen mijn algoritme naar dat van python.

Het probleem dat ik hier vind, is dubbelzijdig:

  1. Mijn waarden lijken vreemd voor iemand die het script probeert te ontcijferen.
  2. Code-onderhoud brengt hoge kosten met zich mee, als die waarden worden gewijzigd (meest waarschijnlijk), of als er nieuwe voorwaarden moeten worden toegevoegd (gebroken schema)

Doe om al deze problemen te omzeilen, je script moet zo gaan

param_Val01 = Value 01   #give a meaningful name for param_Val(i) preferable an integer
param_Val02 = Value 02
param_Val03 = Value 03
param_Val04 = Value 04   # and ... etc
conditions = 0           # this is a value placeholder
########
Add script that if true will make:
conditions = conditions + param_Val01   #value of placeholder is updated
########
### repeat as needed
if conditions = param_Val01 + param_Val02 + param_Val03 + param_Val04:
    do something

Voordelen van deze methode:

  1. Script is leesbaar.

  2. Script kan gemakkelijk worden onderhouden.

  3. voorwaarden is een 1 vergelijkingsbewerking met een som van waarden die de gewenste voorwaarden vertegenwoordigt.
  4. Geen voorwaarden op meerdere niveaus nodig

Ik hoop dat het jullie allemaal helpt

Other episodes