Domanda

A volte rompo le condizioni lunghe in se su più righe. Il modo più ovvio per farlo è:

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

Non è molto accattivante visivamente, 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?

È stato utile?

Soluzione

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

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 allo 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) raccomanda di utilizzare le parentesi quadre.

Altri suggerimenti

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 caratteri e chiarisce che non c'è sottigliezza nella condizione.

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.

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. Ad 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 multilinea, probabilmente mi troverei contento di averle e saltare il refactoring.

D'altra parte, farli turbare 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.

Questo non migliora molto ma ...

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

if allCondsAreOK:
   do_something

Preferisco questo stile quando ho una if-condition terribilmente grande:

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

Suggerisco di spostare la parola chiave e sulla seconda riga e rientrare 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.

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

  

Quando la parte condizionale di un if è 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 rientro naturale di 4 spazi per le righe successive del condizionale multilinea. Ciò può produrre un conflitto visivo con la suite di codice rientrata nidificata all'interno della dichiarazione if , che verrebbe naturalmente rientrata in 4 spazi. Questo PEP non prende posizione esplicita su come (o se) distinguere ulteriormente tali linee condizionali dalla suite nidificata all'interno della dichiarazione if . 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 " 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.

Ecco cosa faccio, ricorda che " tutto " e " qualsiasi " accetta un iterabile, quindi ho inserito una lunga condizione in un elenco e ho lasciato " all " fare il lavoro.

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

if all(condition):
   do_something

Sono sorpreso di non vedere la mia soluzione preferita,

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

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

Personalmente, mi piace aggiungere significato alle if-dichiarazioni 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()

Sicuramente questo potrebbe sembrare a posto, ma leggendoli se le dichiarazioni sono molto impegnative. Che ne dici di assegnare la logica all'etichetta che ha senso. L '"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 archiviare 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 ci siano ragionevoli eccezioni, ricorda: Don't Repeat Yourself (DRY).

" tutto " e " qualsiasi " sono belle 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

(Ho leggermente modificato gli identificativi 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 con " e " e " o " (è importante che siano i primi sulla seconda riga), ma molto meno per le 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 da il 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
}

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 come "virgola mobile".

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 ciclo mentre , è preferibile utilizzare una funzione locale.

Semplice e chiaro, passa anche i controlli pep8:

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

Negli ultimi tempi ho preferito le funzioni all e any , dal momento che raramente mescolo And e O confronti questo funziona bene, e ha l'ulteriore vantaggio di Failing Early con comprensione dei generatori:

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

Ricorda solo di passare in un singolo iterabile! Il passaggio negli argomenti N non è corretto.

Nota: qualsiasi è come molti confronti o , tutto è come molti confronti e .


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

Ulteriori informazioni su: comprensione del generatore

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

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

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 andare.

(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 per non farti sentire così male per il fatto che sono un po 'confusi.)

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.

Ho faticato a trovare anche un modo decente per farlo, quindi mi è venuta un'idea (non un proiettile d'argento, poiché 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), consentendo a tutte le condizioni di allinearsi verticalmente e il corpo dell'istruzione if può essere rientrato in 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 l'idea ennesima , 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()

In un certo senso mi piace perché quando lo guardi, una campana suona immediatamente nella tua testa dicendo "ciao, c'è una cosa complessa che sta succedendo 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 ).

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

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 da if .

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 indentata visivamente con lo stesso rientro della riga logica successiva", il codice effettivo è completamente OK? Non è "quotazione eccessiva"? & Quot;

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

Tutti gli intervistati che forniscono anche multi-condizionali per l'istruzione if sono altrettanto brutti del 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 scriverò letteralmente e lo mangerò per tuo divertimento.

Penso che la soluzione di @ zkanda sarebbe buona con un piccolo colpo di scena. Se avessi le tue condizioni e i valori nei loro rispettivi elenchi, potresti utilizzare 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 esplicito 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 iand operatore :

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

if proceed:
    # do something

Raggruppa le tue condizioni in un elenco, quindi esegui smth. come:

if False not in Conditions:
    do_something

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
  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 es. vedi " Allineato con il delimitatore di apertura " ;:

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

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ò semplifica anche l'aggiunta di un'altra condizione facilmente senza modificare l'istruzione if semplicemente aggiungendo un'altra condizione all'elenco:

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

Di solito uso:

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

se il nostro if & amp; un'altra condizione deve eseguire al suo interno più istruzioni di quante ne possiamo scrivere come di seguito. Ogni volta che abbiamo esempio if else con una dichiarazione 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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top