2013-07-19 12 views
7

In C c'è un trucco intelligente che consente di evitare il codice di piramide in stile girando:Come posso scrivere do-while (0) di C in Python?

if (check1()) 
    if (check2()) 
    if (check3()) 
     do_something(); 

in:

do { 
    if (!check1()) 
    break; 

    if (!check2()) 
    break; 

    if (!check3()) 
    break; 

    do_something(); 
} while (0); 

Qual è il modo più pulito per me di fare questo in Python, che doesn' t avere un costrutto do-while?

Nota: Non sto necessariamente chiedere un modo per implementare un do-while in Python, ma una tecnica per evitare il suddetto codice di piramide in stile.

Aggiornamento: Sembra che ci sia un po 'di confusione. L'unica ragione per cui sto usando un ciclo è di essere in grado di scoppiare in qualsiasi punto del corpo, che dovrebbe essere eseguito una sola volta.

Essenzialmente quello che sto facendo in Python è questo:

while True: 
    if not check1(): 
     break 

    if not check2(): 
     break 

    if not check3(): 
     break 

    do_domething() 
    break 

Mi chiedo solo se c'è un modo più pulito.

+0

'while (0)' <- non potrà mai entrare in questo circuito – inspectorG4dget

+3

@ inspectorG4dget non corretta, la condizione è verificata * dopo * la prima iterazione –

+0

@DrewMcGowen: questo è quello che volevo dire. Verrà eseguito UNA VOLTA e mai più – inspectorG4dget

risposta

-3

In C, l'uso del costrutto do ... while(0) che avete dimostrato di solito è usato quando il programmatore C vuole qualcosa che si comporta come un goto, ma utilizzando un vero e proprio goto è fuori questione (per vari motivi). Quindi, lo break dello do ... while(0) è davvero una specie di hack. Usare lo stesso idioma in Python avrebbe perpetuato quell'hack.

In C, Io in genere evitare di utilizzare questo particolare utilizzo di do ... while(0), e invece optare per una funzione di controllo.In Python, questo sarebbe:

def do_checks(): 
    if not check1(): 
     return False 
    if not check2(): 
     return False 
    if not check3(): 
     return False 
    return True 

if do_checks(): 
    do_something() 

Probabilmente la definizione più diretta della do ... while(0) costrutto di C sarebbe un ciclo con una singola iterazione. Non farlo.

for x in range(1): 
    if not check1(): 
     break 
    if not check2(): 
     break 
    if not check3(): 
     break 
    do_something() 
+0

Accettato come a mio parere, questo più strettamente simula la tecnica "do {...} while (0)" che ho menzionato. –

+7

Questo è orribile. – Blender

+1

-1 Non stai scrivendo Python, stai scrivendo [C-code in Python] (http://programmers.stackexchange.com/questions/96524/96736#96736). –

5

Invertire le condizioni e uscire presto. Se si struttura bene il vostro codice, non dovrete preoccuparvi di if scale, in primo luogo:

def do_bigger_something(): 
    if not check1(): 
     return 

    if not check2(): 
     return 

    if not check3(): 
     return 

    do_something() 

C'è una buona probabilità che se una porzione del codice fa un sacco di questi controlli, dovrebbe essere trasformato in una funzione comunque.

+0

+1 Onestamente, questa è la soluzione migliore * (sia in Python ** che in ** C) * –

+0

Non è una buona soluzione quando check1 (), check2() e check3() prendono tutti più parametri a cui solo il chiamante ha accesso. Quindi il chiamante deve fornire tutti i parametri a do_bigger_something(). –

2
if (check1() and check2() and check3()): 
    do_something() 
1
if check1() and check2() and check3(): 
     do_something() 
+2

Non sarà un loop infinito? –

+0

Mi sono reso conto che mentre lo scrivevo ... ecco perché ora è sparito ... :) –

7

Il modo Pythonic di scrivere questo sarebbe

if check1() and check2() and check3(): 
    do_something() 

In Python si sottolineano chiarezza e semplicità del codice, non usare trucchi di programmazione intelligente.


[Edit] Se è necessario "creare una variabile e utilizzarlo nel primo controllo", quindi si può usare la piramide-style:

if check1(): 
    #variables and stuff here 
    if check2(): 
     #variables and stuff here 
     if check3(): 
      doSomething() 

O, come @Blender suggerisce, refactoring in un metodo separato. Questi sono tutti modi molto più semplici e più chiari di comunicare il tuo intento rispetto all'utilizzo di un ciclo che non è destinato al ciclo.

+0

Mi piace questa soluzione, ma a volte non è così semplice come una chiamata di funzione. Ad esempio, potrei dover creare una variabile e usarla nel primo controllo, che richiederebbe due righe di codice. –

+0

@Brandon: Allora lo scriverai usando il tuo "codice stile Pyramid". Potrebbe avere più indentazione, ma è ancora il modo più semplice e chiaro per scriverlo. –

+0

Ok, capisco il tuo punto. –

1

Direi che se i controlli non sono così banale come questo (che può essere fatto con un semplice and), refactoring del codice e rompere fuori in una funzione invece di mis-utilizzando un ciclo per cose che non è destinato a fare;

def doSomethingIfConditions(): 

    if not check1(): 
    return 

    if not check2(): 
    return 

    if not check3(): 
    return 

    doSomething() 

...your code... 
doSomethingOnConditions() 
...your code... 
0

Soluzione # 1 (semplice):

while True: 
    if not check1(): 
     break 
    if not check2(): 
     break 
    if not check3(): 
     break 
    do_something() 
    break 

Soluzione # 2 (più divinatorio):

for check in check1, check2, check3: 
    if not check(): 
     break 
else: 
    # the else part is only executed 
    # if we didn't break out the loop 
    do_something() 

Soluzione # 3 (ancora più divinatorio):

if all(c() for c in check1,check2, check3): 
    # all(seq) will stop at the first false result 
    do_something() 
+1

E ovviamente la risposta più pitoni è quella di BlueRaja

+0

C'è un problema di rientro, o è un 'else' permesso come parte di un ciclo' for' (invece un 'if')? –

+0

@JonathanLeffler: nessun problema di indentazione, l'istruzione 'for' ha un blocco' else' opzionale che viene eseguito solo se non si interrompe il ciclo. Questo è documentato qui: http://docs.python.org/2/reference/compound_stmts.html#the-for-statement –

0

Non vedo l'esigenza di un loop ... Si interrompe o f alla fine comunque.

if all((check1(), check2(), check3())): 
    print "Do something" 

O semplicemente andare con lo stile di blocco se necessario.

Problemi correlati