Lo stile delle condizioni multilinea nelle istruzioni 'if'? [chiuso]


677

A volte rompo lunghe condizioni in ifs su più linee. Il modo più ovvio per farlo è:

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

Visivamente non è molto accattivante, perché l'azione si fonde con le condizioni. Tuttavia, è il modo naturale di utilizzare il rientro Python corretto di 4 spazi.

Per il momento sto usando:

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

Ma questo non è molto carino. :-)

Puoi consigliarmi un modo alternativo?


2
Se il tuo editor utilizza il pacchetto Python pep8 per rilevare quando avvisare delle violazioni di PEP8 , dovrai disabilitare l'errore E125 o trovare una soluzione di formattazione che soddisfi i pep8criteri del pacchetto. Il pep8del pacchetto di problema # 126 è di circa fissa il pacchetto di seguire rigorosamente le specifiche PEP8. La discussione per il problema include alcuni suggerimenti di stile visti anche qui.
Akaihola,

1
Si noti che per il primo esempio, pep8 genererà "E129 linea indentata visivamente con lo stesso rientro della linea logica successiva".
Taylor Edmiston,

Questa domanda è molto antica e ha un sacco di punti di vista, ma è inequivocabilmente basata sull'opinione. Il linguaggio "non è molto attraente" e "non è molto carino" delinea i criteri secondo cui la risposta presumibilmente corretta è quella che meglio si allinea alle preferenze estetiche dei richiedenti (es. Un'opinione). Potrei fare esattamente la stessa domanda e affermare che non è un duplicato perché il mio gusto estetico lo qualifica come diverso e porterà a una diversa risposta "giusta".
Livello Z4,

@ Livello Z4: sì, è basato sull'opinione. Ma è stato chiesto 12 anni fa. Allora era un posto diverso e più gentile . Recentemente ha accumulato downvotes poiché gli standard di SO sono cambiati. Tuttavia, dopo essere stato visto> 1 milione di volte, spero che stia facendo più bene che male al mondo. Riesco sicuramente a vedere gente che si domanda sulla stessa domanda oggi, cercandola su Google, atterrando su questa discussione e trovando utile calibrare il proprio pensiero. Ci sono diverse risposte altamente votate tra cui scegliere.
Eli Bendersky,

@EliBendersky è completamente d'accordo. È come se SO avesse una crisi d'identità in atto: mentre chiaramente non si adatta alle "regole" (il numero di risposte valide ne è una testimonianza), è altrettanto chiaro che aggiunge valore. A parità di condizioni, preferirei lavorare con qualcuno che avesse sviluppato idee articolabili e ragionate sullo stile di programmazione, anche se le loro opinioni differivano dalle mie.
Z4 livello

Risposte:


750

Non è necessario utilizzare 4 spazi sulla seconda riga condizionale. Forse usare:

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

Inoltre, non dimenticare che lo spazio bianco è più flessibile di quanto potresti pensare:

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

Entrambi però sono abbastanza brutti.

Forse perdere le parentesi (la Guida di stile scoraggia questo però)?

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

Questo almeno ti dà una certa differenziazione.

O anche:

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

Penso di preferire:

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

Ecco la Guida allo stile , che (dal 2010) consiglia di utilizzare le parentesi.


45
Nota che le soluzioni \ finali non sono consigliate da PEP 8. Una ragione è che se uno spazio viene aggiunto per errore dopo un \ potrebbe non essere mostrato nel tuo editor e il codice diventa sintatticamente errato.
Eric O Lebigot,

14
Questo è sbagliato, la guida di stile dice "Le linee lunghe possono essere spezzate su più linee avvolgendo le espressioni tra parentesi. Queste dovrebbero essere usate preferibilmente usando una barra rovesciata per la continuazione della linea." Puoi vederlo qui: python.org/dev/peps/pep-0008/#ma maximum
line

8
@joshcartme Il PEP è cambiato su hg.python.org/peps/rev/7a48207aaab6 per scoraggiare esplicitamente le barre rovesciate. Aggiornerò la risposta.
Harley Holcombe,

3
Grazie, probabilmente è una buona idea aggiornare anche i tuoi esempi poiché ora non sono consigliati. Stavo cercando di capirlo da solo ed ero confuso dalla discrepanza tra la tua risposta e la guida di stile (da qui il mio commento). Non stavo solo cercando di essere pedante.
joshcartme,

3
PEP 8 ora scoraggia anche la rottura dopo il ande if.
virtualxtc

124

Ho fatto ricorso a quanto segue nel caso degenerato in cui si tratta semplicemente di AND o OR.

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

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

Rade alcuni personaggi e chiarisce che non c'è sottigliezza nella condizione.


4
Questo è un approccio interessante. Tuttavia, non affronta il problema delle lunghe condizioni
Eli Bendersky,

20
Va bene se non ti interessa il cortocircuito.
Constantin,

63
lo shortcirtuiting non è sempre veloce. Anche se non codifica buona pratica, si può avere codice come questo esistente: if destroy_world and DestroyTheWorld() == world_is_destroyed: .... Bene, ora hai appena distrutto il mondo per caso. COME HAI POTUTO?
Aaron,

4
Sono sorpreso che questo abbia tanti voti positivi. Questa risposta ignora completamente la domanda originale sullo stile dei condizionali multilinea .
Przemek D,

2
Questa espressione non è pigra. Quindi non è equivalente se alcune condizioni di guardia sono seguite da un possibile fallimento.
eugene-bright

57

Qualcuno deve difendere l'uso dello spazio bianco verticale qui! :)

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

Questo rende ogni condizione chiaramente visibile. Consente inoltre un'espressione più pulita di condizioni più complesse:

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

Sì, stiamo negoziando un po 'di immobili verticali per chiarezza. Ne vale la pena IMO.


19
Questo non sembra essere bello né compatibile con PEP8. PEP8 dice che il luogo preferito per rompere attorno ad un operatore binario (ad esempio and, nonche or) è dopo l'operatore, non prima.
Chris Medrela,

7
@ChristopherMedrela racconta la logica che sta dietro? penso che porre un'interruzione di linea prima che l'operatore logico sia molto più chiaro
Norill Tempest,

4
Mettere al primo posto l'preratore è abbastanza comune nel mondo dei nodi. La logica è che notiamo e leggiamo le cose a sinistra molto più velocemente delle cose a destra - almeno nelle culture occidentali. Molto valido in JavaScript, dove una virgola dimenticata può causare errori silenziosi.
tomekwi,

11
Non farlo per favore. Non solo non lo è, PEP8ma rende più difficile determinare l'operazione logica con cui si sta concatenando. Lo direi se venisse alla mia scrivania attraverso la revisione del codice.
Urda,

11
A partire dalla versione attuale di PEP8, la rottura prima o dopo un operatore binario è considerata accettabile e prima che l'operatore sia considerato migliore per il nuovo codice.
Soren Bjornstad,

31

Preferisco questo stile quando ho una condizione if terribilmente grande:

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

2
+1 per tenere i rientri dove è possibile tenerne traccia. Mi piace Python e lo uso molto, ma sono costantemente infastidito dal fatto di essere costretto a indentare proprio così. La multilinea distrugge davvero l'estetica, anche se eseguita bene.
mightypile,

4
Notare che avere te ande gli oroperatori all'inizio della linea viola PEP 0008 , che afferma "Il posto preferito per interrompere un operatore binario è dopo l'operatore, non prima di esso". . Mi piace avere la parentesi quadra di chiusura e i due punti sulla propria linea per separare la condizione if dal corpo (ed è perfettamente possibile farlo mantenendo gli operatori booleani alla fine della linea per la conformità PEP-0008).
Mark Amery,

8
dal 2016: For decades the recommended style was to break after binary operators. But this can hurt readability in two ways... In Python code, it is permissible to break before or after a binary operator, as long as the convention is consistent locally. For new code Knuth's style is suggested.(lo stile di Knuth è iniziare la linea con l'operatore).
Cowbert,

27

Ecco il mio approccio molto personale: le condizioni lunghe sono (a mio avviso) un odore di codice che suggerisce il refactoring in una funzione / metodo di ritorno booleano. Per esempio:

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

Ora, se trovassi un modo per far apparire bene le condizioni multi-linea, probabilmente mi troverei contento di averle e saltare il refactoring.

D'altro canto, il fatto che abbiano turbato il mio senso estetico funge da incentivo per il refactoring.

La mia conclusione, quindi, è che le condizioni di linea multipla dovrebbero apparire brutte e questo è un incentivo per evitarle.


23

Questo non migliora molto ma ...

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

if allCondsAreOK:
   do_something

1
Alternativa interessante Ma 2 righe extra :-)
Eli Bendersky l'

Non funzionerebbe così bene in un ciclo iterativo, non funzionerebbe con funzioni che fanno qualcosa ... ed essere onesti - brutti
Mez

9
Brian, in parte non sono d'accordo. L'uso di variabili per risultati intermedi di un calcolo può rendere il codice più semplice da comprendere e in un linguaggio compilato non avrà alcun impatto sulle prestazioni. Probabilmente lo farebbe in Python, anche se non userei affatto Python se la performance fosse così importante.
Mark Baker,

1
@MarkBaker Ero d'accordo con quello che hai scritto, fino a quando non ho letto "Refactoring" di Martin Fowlers. Fornisce un eccellente argomento secondo cui tali variabili intermedie causano più danni che benefici. Inibiscono il successivo refactoring. Farne a meno porta a uno stile di programmazione più funzionale, che si presta bene al refactoring. Questo mi ha sorpreso, ma credo che abbia ragione, e da allora mi sono sforzato di eliminare dal mio codice intermedi inutili come questo, anche se vengono utilizzati più di una volta.
Jonathan Hartley,

2
Bene, ma perché camelCase ?! :)
Leonid Shvechikov,

19

Suggerisco di spostare la andparola chiave sulla seconda riga e di rientrare in tutte le righe contenenti condizioni con due spazi anziché quattro:

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

Questo è esattamente il modo in cui risolvo questo problema nel mio codice. Avere una parola chiave come prima parola nella riga rende la condizione molto più leggibile e la riduzione del numero di spazi distingue ulteriormente la condizione dall'azione.


9
Ho letto da qualche parte in Gries o Djikstra che aiutare l'operatore logico in prima linea - rendendo più visibile - ha aiutato. E lo faccio dagli anni '90. E aiuta.
S.

7
Nota che la Guida allo stile consiglia di porre il condizionale alla fine della riga.
Harley Holcombe,

3
È vero, anche se non ci sono mai stato d'accordo su questo. Dopotutto è solo una guida.
DzinX,

8
PEP8 non raccomanda più di mettere il condizionale alla fine della linea.
Soren Bjornstad,

14

Sembra che valga la pena citare PEP 0008 (la guida ufficiale di stile di Python), dal momento che commenta questo problema a bassa lunghezza:

Quando la parte condizionale di un if-statement è abbastanza lunga da richiedere che sia scritta su più righe, vale la pena notare che la combinazione di una parola chiave a due caratteri (cioè if), più un singolo spazio, più una parentesi aperta crea un 4- naturale rientro dello spazio per le righe successive del condizionale multilinea. Ciò può produrre un conflitto visivo con la suite di codice rientrata nidificata all'interno dello ifstato, che verrebbe naturalmente rientrata in 4 spazi. Questo PEP non prende alcuna posizione esplicita su come (o se) distinguere ulteriormente tali linee condizionali dalla suite nidificata all'interno dello ifstato. Le opzioni accettabili in questa situazione includono, ma non sono limitate a:

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

Nota il "non limitato a" nella citazione sopra; oltre agli approcci suggeriti nella guida di stile, anche alcuni di quelli suggeriti in altre risposte a questa domanda sono accettabili.


+1 per PEP8. Questo dovrebbe essere accettato, dal momento che è (praticamente parlando) la guida ufficiale dello stile Python.
Michael - Dov'è Clay Shirky il

2
Vale anche la pena sottolineare che, PEP8 afferma esplicitamente la sua posizione in quanto Questo PEP non prende posizione esplicita su come (o se) distinguere ulteriormente tali linee condizionali dalla suite nidificata all'interno dell'ifstatement. Le opzioni accettabili in questa situazione includono, ma non sono limitate a: ... (frammentato) Quindi, smetti di litigare, scegli qualcosa che ti piace!
RayLuo,

7

Ecco cosa faccio, ricordo che "all" e "any" accetta un iterabile, quindi ho appena messo una lunga condizione in un elenco e lascio che "all" faccia il lavoro.

condition = [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4']

if all(condition):
   do_something

4

Sono sorpreso di non vedere la mia soluzione preferita,

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

Poiché andè una parola chiave, viene evidenziata dal mio editor e sembra sufficientemente diversa da do_something sottostante.


Ma la linea di continuazione non si distingue ancora dalla prossima linea logica ...
Chris Medrela,

1
Si noti che si tratta di una violazione di PEP 0008 ( "Il luogo preferito per interrompere un operatore binario è dopo l'operatore, non prima di esso" ). Se ti interessa, ovviamente, dipende da te.
Mark Amery,

1
Per inciso, questa non è più la mia soluzione preferita. ;)
Marius Gedminas il

4

In aggiunta a ciò che ha detto @krawyoti ... Le lunghe condizioni hanno un odore perché sono difficili da leggere e difficili da capire. L'uso di una funzione o di una variabile rende il codice più chiaro. In Python, preferisco usare lo spazio verticale, racchiudere le parentesi e posizionare gli operatori logici all'inizio di ogni riga in modo che le espressioni non appaiano "fluttuanti".

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

Se le condizioni devono essere valutate più di una volta, come in un whileciclo, è consigliabile utilizzare una funzione locale.


1
Inoltre, puoi dichiarare una funzione o un lambda per restituire il tuo vero falso invece di creare una variabile aggiuntiva.
Techdragon,

@Techdragon se le condizioni devono essere altrove, quindi inserirle in un blocco lambda richiederebbe il nome del blocco lambda in modo che possa fare riferimento in seguito nella condizione if. Se un lambda verrà chiamato, perché dopo tutto e non una normale funzione? Personalmente mi piace questa espressione booleana ridotta.
Sri Kadimisetty,

Sono d'accordo, motivo per cui normalmente userei una funzione nella maggior parte dei casi sia per migliorare la leggibilità sia per facilitare la digestione mentale quando parto per capire il flusso di controllo del programma. Cito la lambda per garantire che l'opzione "più piccola" sia presente anche nel caso in cui le persone siano particolarmente attente allo spazio.
Techdragon,

4

Personalmente, mi piace aggiungere un significato alle dichiarazioni if ​​lunghe. Dovrei cercare nel codice per trovare un esempio appropriato, ma ecco il primo esempio che mi viene in mente: diciamo che mi capita di imbattermi in una logica eccentrica in cui voglio visualizzare una determinata pagina in base a molte variabili.

Inglese: "Se l'utente che ha effettuato l'accesso NON è un insegnante amministratore, ma è solo un insegnante normale e non è uno studente stesso ..."

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

Certo, potrebbe sembrare perfetto, ma leggere quelle se le dichiarazioni è molto impegnativo. Che ne dici di assegnare la logica all'etichetta che ha senso. La "etichetta" è in realtà il nome della variabile:

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

Questo può sembrare sciocco, ma potresti avere ancora un'altra condizione in cui desideri visualizzare SOLO un altro elemento se, e solo se, stai visualizzando il pannello dell'insegnante O se l'utente ha accesso a quell'altro pannello specifico per impostazione predefinita:

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

Prova a scrivere la condizione precedente senza usare le variabili per memorizzare ed etichettare la tua logica, e non solo ti ritrovi con un'istruzione logica molto disordinata e difficile da leggere, ma ti sei anche ripetuto. Sebbene vi siano ragionevoli eccezioni, ricorda: non ripetere (DRY).


3

"all" e "any" sono utili per le molte condizioni del caso dello stesso tipo. MA valutano sempre tutte le condizioni. Come mostrato in questo esempio:

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

5
! non corretta Lo fanno solo perché lo fai. Prova tutto (f () per f in [c1, c2]).
habnabit,

2
Penso che stesse usando le funzioni solo come esempio, perché può facilmente farle stampare qualcosa. Se stiamo prendendo in considerazione una serie di espressioni arbitrarie fornite in un elenco fino a all()quel momento, a meno che non le avvolgerai ognuna in un lambda e utilizzi il tuo f()trucco, verranno tutte valutate. In altre parole, Aaron: penso che Anders stesse cercando di parlare delle condizioni in generale, usando i callable come esempio specifico; ma la tua controreplica si applica solo alle funzioni.
Brandon Rhodes,

3

(Ho leggermente modificato gli identificatori poiché i nomi a larghezza fissa non sono rappresentativi del codice reale - almeno non del codice reale che incontro - e crederò alla leggibilità di un esempio.)

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

Funziona bene per "e" e "o" (è importante che siano i primi sulla seconda riga), ma molto meno per altre condizioni lunghe. Fortunatamente, il primo sembra essere il caso più comune mentre i secondi sono spesso facilmente riscritti con una variabile temporanea. (Di solito non è difficile, ma può essere difficile o molto meno ovvio / leggibile preservare il corto circuito di "e" / "o" ​​durante la riscrittura.)

Da quando ho trovato questa domanda dal tuo post sul blog su C ++ , includerò che il mio stile C ++ è identico:

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

3

Chiaro e semplice, passa anche i controlli pep8:

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

Negli ultimi tempi ho preferito le funzioni alle any, dal momento che raramente mescolo And and Or confronti funziona bene, e ha il vantaggio aggiuntivo di Failing Early con la comprensione dei generatori:

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

Basta ricordare di passare in un unico iterabile! Il passaggio negli argomenti N non è corretto.

Nota: anyè come molti orconfronti, allè come molti andconfronti.


Questo si combina perfettamente con la comprensione del generatore, ad esempio:

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

Maggiori informazioni su: comprensione del generatore


1
Vorrei anche sottolineare che la configurazione di stock di Pylint vuole un seguito indentale sulla linea in un if; che mi ha dissuaso dall'uso di questo schema.
ThorSummoner,

2

Che cosa succede se inseriamo solo una riga vuota aggiuntiva tra la condizione e il corpo e facciamo il resto in modo canonico?

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

    do_something

ps Uso sempre le schede, non gli spazi; Non riesco a mettere a punto ...


3
Questo sarebbe molto confuso, specialmente quando il corpo del condizionale è lungo, credo.
Eli Bendersky,

Sono d'accordo con Eli, l'incapsulamento e il rientro qui sono confusi per le lunghe battute. Inoltre, la nuova regola è che le istruzioni ande ordovrebbero iniziare sulla riga successiva
virtualxtc,

2

Quello che faccio di solito è:

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

in questo modo la parentesi graffa di chiusura e i due punti segnano visivamente la fine della nostra condizione.


1
Quasi corretto; PEP 8 ora consiglia di interrompere prima ando or.
virtualxtc,

2

Tutti gli intervistati che forniscono anche multi-condizionali per l'istruzione if sono brutti quanto il problema presentato. Non risolvi questo problema facendo la stessa cosa ..

Anche la risposta PEP 0008 è ripugnante.

Ecco un approccio molto più leggibile

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

Vuoi che mangio le mie parole? Convincimi che hai bisogno di multi-condizionali e lo stampa letteralmente e lo mangio per il tuo divertimento.


questo è davvero un modo molto semplice di fare multi-condizionali :) non so perché non ha più voti :), ci sono avvertenze?
dim_user

@SaulCruz non c'è davvero Non solo la variabile di condizione non deve essere ripetuta, ma si salva anche sui molti duplicati della verifica di ciascun valore, questo mette semplicemente i valori in un array e lascia che il motore faccia il suo lavoro (ottimizzato) in controllando le condizioni per te
Stoff

@Stoff Grazie per aver rimosso il mio commento. Volevo sottolineare che il vostro approccio non risponde alla domanda del PO. Il codice fornito non può essere applicato al codice nella domanda. Se la pensi diversamente, dovresti aggiungere il codice OP riformattato dal tuo approccio per dimostrare il tuo punto.
Jeyekomon,

Non è la risposta accettata, ma è chiaramente un approccio alternativo (altri concordano). Quindi incoraggiato le risposte alternative, quindi qual è esattamente l'argomento? Sii chiaro nella tua domanda, forse considera di aprire la tua domanda se hai bisogno della giusta attenzione. Ps Non sono un mod SO, non posso rimuovere i commenti
Stoff

2

Penso che la soluzione di @ zkanda sarebbe buona con un piccolo colpo di scena. Se avessi le tue condizioni e i tuoi valori nei loro rispettivi elenchi, potresti usare una comprensione dell'elenco per fare il confronto, il che renderebbe le cose un po 'più generali per l'aggiunta di coppie condizione / valore.

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

Se volessi codificare in modo affermativo un'istruzione come questa, la scriverei in questo modo per leggibilità:

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

E solo per lanciare un'altra soluzione là fuori con un iandoperatore :

proceed = True
for c, v in zip(conditions, values):
    proceed &= c==v

if proceed:
    # do something

1
Solo per divertimento: all(map(eq, have, expected)). (con from operator import eq)
Gabriel Garcia,

1

Solo poche altre idee casuali per completezza. Se funzionano per te, usali. Altrimenti, probabilmente stai meglio provando qualcos'altro.

Puoi anche farlo con un dizionario:

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

Questa opzione è più complicata, ma potresti anche trovarla utile:

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

Non so se funziona per te, ma è un'altra opzione da considerare. Ecco un altro modo:

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'

Gli ultimi due che non ho testato, ma i concetti dovrebbero essere sufficienti per farti andare se è quello che vuoi seguire.

(E per la cronaca, se questa è solo una cosa, probabilmente stai solo meglio usando il metodo che hai presentato all'inizio. Se stai facendo il confronto in molti posti, questi metodi potrebbero migliorare la leggibilità abbastanza da rendere non ti senti così male per il fatto che sono un po 'confusi).


1

Ho faticato a trovare anche un modo decente per farlo, quindi mi è venuta un'idea (non un proiettile d'argento, dato che si tratta principalmente di una questione di gusti).

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

Trovo alcuni meriti in questa soluzione rispetto ad altri che ho visto, vale a dire, ottieni esattamente altri 4 spazi di rientro (bool), permettendo a tutte le condizioni di allinearsi verticalmente e il corpo dell'istruzione if può essere indentato in un modo chiaro (ish). Ciò mantiene anche i vantaggi della valutazione del corto circuito degli operatori booleani, ma ovviamente aggiunge il sovraccarico di una chiamata di funzione che sostanzialmente non fa nulla. Potresti sostenere (validamente) che qualsiasi funzione che restituisce il suo argomento potrebbe essere usata qui invece di bool, ma come ho detto, è solo un'idea ed è in definitiva una questione di gusti.

Abbastanza divertente, mentre stavo scrivendo questo e pensando al "problema", mi è venuta in mente un'altra idea, che rimuove l'overhead di una chiamata di funzione. Perché non indicare che stiamo per entrare in una condizione complessa usando coppie extra di parentesi? Dì, altri 2, per dare un bel rientro di 2 spazi delle sotto-condizioni relative al corpo dell'istruzione if. Esempio:

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

Mi piace un po 'perché quando lo guardi, una campana suona immediatamente nella tua testa dicendo "ehi, c'è una cosa complessa che succede qui!" . Sì, so che le parentesi non aiutano la leggibilità, ma queste condizioni dovrebbero apparire abbastanza raramente e quando si presentano, dovrai fermarti a leggerle attentamente (perché sono complesse ).

Ad ogni modo, solo altre due proposte che non ho visto qui. Spero che questo aiuti qualcuno :)


1

Potresti dividerlo in due righe

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

O anche aggiungere una condizione alla volta. In questo modo, almeno separa il disordine dal if.


1

So che questo thread è vecchio, ma ho del codice Python 2.7 e PyCharm (4.5) si lamenta ancora di questo caso:

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

Anche con l'avvertimento PEP8 "riga visivamente indentata con lo stesso rientro della riga logica successiva", il codice effettivo è completamente OK? Non è "indentazione eccessiva?"

... ci sono volte in cui vorrei che Python avesse morso il proiettile e se ne fosse andato con le parentesi graffe. Mi chiedo quanti bug sono stati introdotti accidentalmente nel corso degli anni a causa di errata indentazione ...


0

Inserisci le tue condizioni in un elenco, quindi esegui smth. piace:

if False not in Conditions:
    do_something

0

Trovo che quando ho condizioni lunghe, spesso ho un corpo di codice breve. In tal caso, ho solo un doppio rientro del corpo, quindi:

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

1
@qarma, ti andrebbe di espandersi? È sicuramente meglio dell'uso di caratteri di continuazione di riga, che sono raccomandati contro PEP 8
xorsyst

Questo è in realtà un caso valido per la continuazione della linea. Le parentesi IMPO indicano una tupla o una chiamata di funzione. L'uso di OP è molto simile al C, preferisco la sintassi di Python quando possibile. Ammetto che \ non è universalmente preferito però.
Dima Tisnek,

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

o se questo è più chiaro:

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

Non vi è alcun motivo per cui il rientro dovrebbe essere un multiplo di 4 in questo caso, ad esempio vedere "Allineato con delimitatore di apertura":

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


La guida di Google fornisce anche un esempio di una condizione complessa , che corrisponde a "il modo più ovvio per farlo", come indicato dal PO. Sebbene la guida non sostenga esplicitamente la formattazione lunga "se" in questo modo.
Anton Strogonoff,

0

Ecco un altro approccio:

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

Ciò consente inoltre di aggiungere facilmente un'altra condizione senza modificare l'istruzione if semplicemente aggiungendo un'altra condizione all'elenco:

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

0

Di solito uso:

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

0

se la nostra condizione if & an else deve eseguire al suo interno più istruzioni di quante ne possiamo scrivere come di seguito. Ogni volta che abbiamo esempio if else con una frase al suo interno.

Grazie ha funzionato per me.

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

0

Perdonate il mio noobness, ma capita che io non sia così informato di #Python come chiunque di voi qui, ma succede che ho trovato qualcosa di simile durante lo scripting dei miei oggetti in un modello 3D BIM, quindi adatterò il mio algoritmo a quello di Python.

Il problema che trovo qui è a doppia faccia:

  1. I miei valori sembrano estranei a qualcuno che potrebbe provare a decifrare la sceneggiatura.
  2. La manutenzione del codice avrà un costo elevato, se tali valori vengono modificati (molto probabilmente) o se è necessario aggiungere nuove condizioni (schema non funzionante)

Fai per evitare tutti questi problemi, il tuo script deve andare così

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

Pro di questo metodo:

  1. Lo script è leggibile.

  2. Lo script può essere facilmente gestito.

  3. condizioni è un'operazione di confronto 1 con una somma di valori che rappresenta le condizioni desiderate.
  4. Non sono necessarie condizioni multilivello

Spero che ti aiuti tutti

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.