383 votes

Clause Else sur l'instruction Python while

J'ai remarqué que le code suivant est légal en Python. Ma question est la suivante : pourquoi ? Y a-t-il une raison spécifique ?

n = 5
while n != 0:
    print n
    n -= 1
else:
    print "what the..."

De nombreux débutants tombent accidentellement sur cette syntaxe lorsqu'ils essaient de mettre une balise <code>if</code> / <code>else</code> à l'intérieur d'un bloc <code>while</code> o <code>for</code> et n'indentez pas les <code>else</code> correctement. La solution consiste à s'assurer que le <code>else</code> s'aligne sur le bloc <code>if</code> en supposant que c'était votre intention de les jumeler. Cette question explique <em>pourquoi cela n'a pas provoqué d'erreur de syntaxe </em>y <em>ce que signifie le code qui en résulte. </em>Voir aussi <a href="https://stackoverflow.com/questions/45621722">Je reçois un IndentationError. Comment puis-je le corriger ? </a>pour les cas où il y a <em>es </em>une erreur de syntaxe a été signalée.

11 votes

@detly : C'est parce que la plupart des gens évitent cette construction. :) Je crois que Guido a mentionné pendant le processus Py3k que, à tout le moins, le choix du mot else pour cet usage avait été une très mauvaise idée, et qu'ils n'en feraient pas d'autres.

6 votes

Nicholas Knight - Oui, aussi tentant que cela puisse être, ce serait probablement quelque chose que je serais le seul à comprendre à première vue. N'importe quel autre pauvre nigaud devrait aller voir les spécifications du langage, ou remonter dans le temps et poster une question ici sur Sta- heeeeey...

1 votes

@detly Quel serait un meilleur mot qu'autre chose ?

456voto

ars Points 35803

En else n'est exécutée que lorsque votre while la condition devient fausse. Si vous break en dehors de la boucle, ou si une exception est levée, il ne sera pas exécuté.

On peut y penser comme à une construction if/else par rapport à la condition :

if condition:
    handle_true()
else:
    handle_false()

est analogue à la construction en boucle :

while condition:
    handle_true()
else:
    # condition is false now, handle and go on with the rest of the program
    handle_false()

Un exemple pourrait être le suivant :

while value < threshold:
    if not process_acceptable_value(value):
        # something went wrong, exit the loop; don't pass go, don't collect 200
        break
    value = update(value)
else:
    # value >= threshold; pass go, collect 200
    handle_threshold_reached()

68 votes

"La clause else n'est exécutée que lorsque votre condition while devient fausse." La formulation ici implique que votre condition while passe d'un état de vrai à faux et que la clause else sera exécutée. Toutefois, si la condition while n'est jamais vraie, la clause else sera quand même exécutée.

2 votes

pseudo-code Corrigez-moi si je me trompe, mais c'est exactement la même chose que while {} something sauf que le something sera ignoré si vous break en el while boucle.

2 votes

Le pseudocode le plus précis serait peut-être : while(True) { if (cond) { handle_true() ; } else { handle_false() ; break ; } }

131voto

John Kugelman Points 108754

En else est exécutée si vous sortez d'un bloc normalement, en frappant la condition de la boucle ou en tombant en bas d'un bloc try. Elle est pas exécuté si vous break o return de sortir d'un bloc, ou de lever une exception. Cela fonctionne non seulement pour les boucles while et for, mais aussi pour les blocs try.

On le trouve généralement dans des endroits où, normalement, on devrait sortir d'une boucle plus tôt, et où le fait de sortir de la fin de la boucle est une occasion inattendue ou inhabituelle. Par exemple, si vous parcourez une liste à la recherche d'une valeur :

for value in values:
    if value == 5:
        print "Found it!"
        break
else:
    print "Nowhere to be found. :-("

2 votes

En fait, c'est une construction assez utile pour une telle chose. Je ne sais pas combien de fois j'ai mis found_it=False au début d'une boucle, et ensuite faire une vérification if sur found_it à la fin

42voto

Mark Points 1278

En réponse à Is there a specific reason? Dans le cadre de la mise en œuvre du programme, voici une application intéressante : l'élimination des niveaux multiples de bouclage.

Voici comment cela fonctionne : la boucle extérieure a une pause à la fin, elle ne sera donc exécutée qu'une seule fois. Toutefois, si la boucle intérieure se termine (elle ne trouve pas de diviseur), elle atteint l'instruction else et la pause extérieure n'est jamais atteinte. De cette façon, une interruption dans la boucle intérieure entraînera l'interruption des deux boucles, et non d'une seule.

for k in [2, 3, 5, 7, 11, 13, 17, 25]:
    for m in range(2, 10):
        if k == m:
            continue
        print 'trying %s %% %s' % (k, m)
        if k % m == 0:
            print 'found a divisor: %d %% %d; breaking out of loop' % (k, m)
            break
    else:
        continue
    print 'breaking another level of loop'
    break
else:
    print 'no divisor could be found!'

Pour les deux while y for boucles, les else est exécutée à la fin, sauf si break a été utilisé.

Dans la plupart des cas, il existe de meilleures façons de le faire (en l'intégrant dans une fonction ou en levant une exception), mais cette méthode fonctionne !

1 votes

Je n'ai pas déclassé mais je pense savoir pourquoi quelqu'un l'a fait. Vous ne répondez pas à la question et vous fournissez 14 lignes de code avec seulement 2 lignes de description. S'il y a un rapport avec la question posée, vous ne nous le dites pas...

1 votes

@BlueEel merci pour le feedback ! J'ai ajouté plus d'explications sur le code, et j'ai précisé comment il répond à la question (car il y répond en partie).

0 votes

Vous avez réussi à mettre votre code en contexte et, même si vous ne répondez pas à toutes les questions, je vois maintenant la pertinence. J'ai upvoted votre réponse car elle est maintenant utile aux nouveaux arrivants et aux novices (comme moi en ce qui concerne python). - Merci, j'ai appris quelque chose.

26voto

Mark Rushakoff Points 97350

La clause else est exécutée lorsque la condition while vaut false.

De la documentation :

L'instruction while est utilisée pour une exécution répétée tant qu'une expression est vraie :

while_stmt ::=  "while" expression ":" suite
                ["else" ":" suite]

Cela teste l'expression de manière répétée et, si elle est vraie, exécute la première suite ; si l'expression est fausse (ce qui peut être la première fois qu'elle est testée), la suite de l'option else si elle est présente, est exécutée et la boucle se termine.

A break exécutée dans la première suite met fin à la boucle sans exécuter l'instruction else la suite de la clause. A continue exécutée dans la première suite ignore le reste de la suite et retourne tester l'expression.

0voto

BoltClock Points 249668

En else: est exécutée lorsque, et seulement lorsque, la boucle while ne remplit plus sa condition (dans votre exemple, lorsque n != 0 est fausse).

Le résultat serait donc le suivant :

5
4
3
2
1
what the...

0 votes

Je sais mais ce genre de while/else ne fonctionne pas en Java. J'ai trouvé cela très intéressant lorsque j'ai compris que cela fonctionnait en Python. J'étais juste curieux et je voulais connaître la raison technique.

6 votes

Ce n'est pas tant qu'il n'y a pas d'autre solution. travail en Java mais qu'il ne existe en Java. Il serait possible de le faire fonctionner, si quelqu'un se souciait de l'ajouter au langage.

1 votes

Non, while False : .. else exécute toujours la clause else. Il est plus exact de dire : else n'est pas exécuté si la boucle est interrompue.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X