Je comprends comment cette construction fonctionne:
for i in range(10):
print(i)
if i == 9:
print("Too big - I'm giving up!")
break;
else:
print("Completed successfully")
Mais je ne comprends pas pourquoi else
est utilisé comme mot-clé ici, car il suggère que le code en question ne s'exécute que si le for
bloc ne se termine pas, ce qui est l'opposé de ce qu'il fait! Peu importe comment j'y pense, mon cerveau ne peut pas évoluer de manière transparente de la for
déclaration au else
bloc. Pour moi, continue
ou continuewith
aurait plus de sens (et j'essaie de m'entraîner à le lire comme tel).
Je me demande comment les codeurs Python lisent cette construction dans leur tête (ou à haute voix, si vous le souhaitez). Peut-être que je manque quelque chose qui rendrait ces blocs de code plus facilement déchiffrables?
python
if-statement
for-loop
for-else
Kent Boogaart
la source
la source
break
est beaucoup utilisé dans les boucles "je l'ai trouvé" , vous pouvez le traduire en "s'il n'est pas trouvé" , ce qui n'est pas loin de ce qui seelse
litfor ... else foo()
et juste mettrefoo()
après la boucle for?" Et la réponse est qu'ils se comportent différemment uniquement si la boucle contient unbreak
(comme décrit en détail ci-dessous).Réponses:
C'est une construction étrange, même pour les codeurs Python chevronnés. Lorsqu'il est utilisé en conjonction avec des boucles for, cela signifie essentiellement "trouver un élément dans l'itérable, sinon si aucun n'a été trouvé, faites ...". Un péché:
Mais chaque fois que vous voyez cette construction, une meilleure alternative consiste à encapsuler la recherche dans une fonction:
Ou utilisez une liste de compréhension:
Il n'est pas sémantiquement équivalent aux deux autres versions, mais fonctionne assez bien dans le code critique sans performances où il importe peu que vous itériez la liste entière ou non. D'autres peuvent être en désaccord, mais personnellement, j'éviterais d'utiliser les blocs for-else ou while-else dans le code de production.
Voir aussi [Python-ideas] Résumé des fils de discussion for ... else
la source
for
exemples de boucle, et que vous souhaitez utiliser une expression de générateur / compréhension de liste, alors vous vouleznext((o for o in objects if o.key == search_key), None)
ou l'encapsuler dans untry
/except
et n'utilisez aucune valeur par défaut au lieu d'unif
/else
.for/else
construction.else
s'est apparié avec unfor
et je n'avais aucune idée que c'était légal.break
instruction est explicitement exécutée comme dans cet exemple. D'après les documents ci-dessus: "Laelse
clause a un autre problème perçu: s'il n'y en a pasbreak
dans la boucle, laelse
clause est fonctionnellement redondante.". par exemplefor x in [1, 2, 3]:\n print x\n else:\n print 'this executes due to no break'
Une construction courante consiste à exécuter une boucle jusqu'à ce que quelque chose soit trouvé, puis à sortir de la boucle. Le problème est que si je sors de la boucle ou si la boucle se termine, je dois déterminer quel cas s'est produit. Une méthode consiste à créer un indicateur ou une variable de stockage qui me permettra de faire un deuxième test pour voir comment la boucle a été quittée.
Par exemple, supposons que je dois rechercher dans une liste et traiter chaque élément jusqu'à ce qu'un élément indicateur soit trouvé, puis arrêter le traitement. Si l'élément indicateur est manquant, une exception doit être déclenchée.
En utilisant la construction Python
for
...else
vous avezComparez cela à une méthode qui n'utilise pas ce sucre syntaxique:
Dans le premier cas, le
raise
est étroitement lié à la boucle for avec laquelle il fonctionne. Dans le second cas, la liaison n'est pas aussi solide et des erreurs peuvent être introduites lors de la maintenance.la source
Python: the good parts
livre.process(i)
cela se produit pour chaque élémentmylist
strictement avanttheflag
, et non pourtheflag
lui-même? Est-ce que c'était prévu?process
s'exécutera sur chacuni
qui existe dans la liste avant qu'iltheflag
soit atteint, il ne sera pas exécuté sur les éléments de la liste aprèstheflag
, et il ne sera pas exécuté surtheflag
.Il y a une excellente présentation de Raymond Hettinger, intitulée Transforming Code into Beautiful, Idiomatic Python , dans laquelle il aborde brièvement l'histoire de la
for ... else
construction. La section pertinente est "Distinguer plusieurs points de sortie en boucles" à partir de 15h50 et se poursuivant pendant environ trois minutes. Voici les points forts:for ... else
construction a été conçue par Donald Knuth en remplacement de certainsGOTO
cas d'utilisation;else
mot - clé était logique parce que "c'est ce que Knuth a utilisé, et les gens savaient, à ce moment-là, que toutes les [for
déclarations] avaient intégré unif
et enGOTO
dessous, et ils s'attendaient à ce que leelse
";Donc, si la question est: "Pourquoi ne modifient-ils pas ce mot-clé?" alors Cat Plus Plus a probablement donné la réponse la plus précise - à ce stade, il serait trop destructeur pour le code existant pour être pratique. Mais si la question que vous vous posez vraiment est pourquoi a
else
été réutilisée en premier lieu, eh bien, apparemment, cela semblait être une bonne idée à l'époque.Personnellement, j'aime le compromis de commenter
# no break
en ligne partout où leelse
pourrait être confondu, en un coup d'œil, comme appartenant à l'intérieur de la boucle. C'est assez clair et concis. Cette option est brièvement mentionnée dans le résumé que Bjorn a lié à la fin de sa réponse:* Citation supplémentaire de cette partie de la vidéo: "Tout comme si nous appelions lambda makefunction, personne ne demanderait:" Que fait lambda? ""
la source
Parce qu'ils ne voulaient pas introduire un nouveau mot-clé dans la langue. Chacun vole un identifiant et cause des problèmes de compatibilité descendante, c'est donc généralement un dernier recours.
la source
finally
cela aurait été un meilleur choix dans ce cas. Le mot clé finally n'était-il pas encore présent au moment de l'introduction de cette construction?finally
n'est pas beaucoup mieux, car cela implique que le bloc sera toujours exécuté après la boucle, et ce n'est pas le cas (car ce serait redondant en mettant simplement le code à exécuter après la boucle).finally
dû au fait que la clause else est exécutée également lorsqu'ellecontinue
est utilisée dans la boucle for - c'est-à-dire plusieurs fois et pas seulement à la fin.else
exécution de la clause @pepr n'est pas affectée parcontinue
( documents et code de test )else
n'est exécuté que lorsque lecontinue
était celui de la dernière itération.Pour faire simple, vous pouvez penser à cela comme ça;
break
commande dans lafor
boucle, laelse
pièce ne sera pas appelée.break
commande dans lafor
boucle, laelse
pièce sera appelée.En d'autres termes, si pour l'itération de boucle n'est pas "rompue" avec
break
, laelse
partie sera appelée.la source
else
bloc ne sera également pas exécuté si le corps de la boucle lève une exception.Le moyen le plus simple que j'ai trouvé pour `` obtenir '' ce que le for / else a fait, et plus important encore, quand l'utiliser, était de se concentrer sur l'endroit où l'instruction break saute. La construction For / else est un seul bloc. La coupure saute hors du bloc, et saute ainsi par dessus la clause else. Si le contenu de la clause else suivait simplement la clause for, il ne serait jamais sauté, et donc la logique équivalente devrait être fournie en la mettant dans un if. Cela a déjà été dit, mais pas tout à fait dans ces mots, donc cela peut aider quelqu'un d'autre. Essayez d'exécuter le fragment de code suivant. Je suis de tout coeur en faveur du commentaire "no break" pour plus de clarté.
la source
for:
/else:
, il ne fournit pas vraiment de justification pour le mot-cléelse
. Compte tenu du cadrage donné ici, ilthen:
semble que ce serait beaucoup plus naturel. (Il y a des raisons d'else
être choisies, données dans d'autres réponses - elles ne sont tout simplement pas fournies ici.)Je pense que la documentation a une grande explication d' autre , continuez
Source: Python 2 docs: Tutoriel sur le flux de contrôle
la source
Je l'ai lu quelque chose comme:
Si vous êtes toujours dans les conditions pour exécuter la boucle, faites des choses, sinon faites autre chose.
la source
for:
/else:
donne l'impression que leelse:
sera toujours exécuté après la boucle, ce qui n'est pas le cas.Depuis la partie technique a été à peu près répondu, mon commentaire est juste en relation avec la confusion qui produit ce mot-clé recyclé .
Étant Python un langage de programmation très éloquent , l'utilisation abusive d'un mot-clé est plus notoire. Le
else
mot-clé décrit parfaitement une partie du flux d'un arbre de décision, "si vous ne pouvez pas faire ceci, (sinon) faites cela". C'est implicite dans notre propre langue.Au lieu de cela, l'utilisation de ce mot clé avec les instructions
while
etfor
crée de la confusion. La raison, notre carrière en tant que programmeurs nous a appris que laelse
déclaration réside dans un arbre de décision; sa portée logique , un wrapper qui renvoie conditionnellement un chemin à suivre. Pendant ce temps, les instructions de boucle ont un objectif explicite figuratif pour atteindre quelque chose. L'objectif est atteint après des itérations continues d'un processus.if / else
indiquer un chemin à suivre . Les boucles suivent un chemin jusqu'à ce que le «but» soit terminé .Le problème est que
else
c'est un mot qui définit clairement la dernière option d'une condition. La sémantique du mot est partagée par Python et Human Language. Mais le mot else en langage humain n'est jamais utilisé pour indiquer les actions qu'une personne ou quelque chose entreprendra après que quelque chose soit terminé. Il sera utilisé si, dans le processus de le terminer, un problème survient (plus comme une déclaration de rupture ).À la fin, le mot-clé restera en Python. Il est clair que c'était une erreur, plus clair quand chaque programmeur essaie de trouver une histoire pour comprendre son utilisation comme un appareil mnémotechnique. J'aurais adoré s'ils choisissaient plutôt le mot-clé
then
. Je crois que ce mot-clé s'intègre parfaitement dans ce flux itératif, le gain après la boucle.Cela ressemble à cette situation que certains enfants ont après avoir suivi chaque étape de l'assemblage d'un jouet: Et PUIS quoi papa?
la source
Je l'ai lu comme "Lorsque le
iterable
est complètement épuisé et que l'exécution est sur le point de passer à l'instruction suivante après avoir terminé lefor
, la clause else sera exécutée." Ainsi, lorsque l'itération est interrompuebreak
, cela ne sera pas exécuté.la source
Je suis d'accord, c'est plutôt un «elif pas [condition (s) soulevant la pause]».
Je sais que c'est un vieux fil, mais je regarde la même question en ce moment, et je ne suis pas sûr que quiconque ait saisi la réponse à cette question de la façon dont je la comprends.
Pour moi, il existe trois façons de "lire" les instructions
else
inFor... else
ouWhile... else
, qui sont toutes équivalentes, sont les suivantes:else
==
if the loop completes normally (without a break or error)
else
==
if the loop does not encounter a break
else
==
else not (condition raising break)
(sans doute existe-t-il une telle condition, sinon vous n'auriez pas de boucle)Donc, essentiellement, le "else" dans une boucle est vraiment un "elif ..." où '...' est (1) pas de rupture, ce qui équivaut à (2) PAS [condition (s) augmentant la rupture].
Je pense que la clé est que le
else
est inutile sans la «pause», donc unfor...else
comprend:Ainsi, les éléments essentiels d'une
for...else
boucle sont les suivants, et vous les liriez en anglais plus simple:Comme les autres affiches l'ont dit, une pause est généralement déclenchée lorsque vous êtes en mesure de localiser ce que recherche votre boucle, de sorte que
else:
devient "ce qu'il faut faire si l'élément cible n'est pas localisé".Exemple
Vous pouvez également utiliser la gestion des exceptions, les interruptions et les boucles for ensemble.
Résultat
Exemple
Exemple simple avec coupure.
Résultat
Exemple
Exemple simple où il n'y a aucune interruption, aucune condition provoquant une interruption et aucune erreur n'est rencontrée.
Résultat
la source
Le
else
mot-clé peut être déroutant ici, et comme beaucoup de gens l'ont souligné, quelque chose commenobreak
,notbreak
est plus approprié.Afin de comprendre
for ... else ...
logiquement, comparez-le avectry...except...else
, nonif...else...
, la plupart des programmeurs python connaissent le code suivant:De même, pensez
break
à un type spécial deException
:La différence est
python
impliciteexcept break
et vous ne pouvez pas l'écrire, cela devient donc:Oui, je sais que cette comparaison peut être difficile et fastidieuse, mais elle clarifie la confusion.
la source
Les codes dans le
else
bloc d'instructions seront exécutés lorsque lafor
boucle n'a pas été rompue.À partir des documents: rompre et continuer les instructions, et sinon les clauses sur les boucles
la source
Voici une façon d'y penser que je n'ai vu personne mentionner ci-dessus:
Tout d'abord, rappelez-vous que les boucles for ne sont fondamentalement que du sucre syntaxique autour des boucles while. Par exemple, la boucle
peut être réécrit (environ) comme
Deuxièmement, rappelez-vous que les boucles while sont essentiellement des blocs if simplement répétés! Vous pouvez toujours lire une boucle while comme "si cette condition est vraie, exécutez le corps, puis revenez et vérifiez à nouveau".
Donc, tandis que / else est parfaitement logique: c'est exactement la même structure que si / else, avec la fonctionnalité supplémentaire de bouclage jusqu'à ce que la condition devienne fausse au lieu de simplement vérifier la condition une fois.
Et puis, for / else est également parfaitement logique: parce que toutes les boucles for ne sont que du sucre syntaxique au-dessus des boucles while, il vous suffit de comprendre ce qu'est le conditionnel implicite de la boucle while sous-jacente, puis le reste correspond à quand cela condition devient Faux.
la source
Les bonnes réponses sont:
Ma note ici vient de ce que Donald Knuth a dit un jour (désolé, je ne trouve pas de référence) qu'il existe une construction où while-else est indiscernable de if-else, à savoir (en Python):
a le même flux (hors faibles différences de niveau) que:
Le fait est que if-else peut être considéré comme du sucre syntaxique pour while-else qui a implicite
break
à la fin de sonif
bloc. L'implication opposée, à laquelle cettewhile
boucle est l'extensionif
, est plus courante (il s'agit simplement d'une vérification conditionnelle répétée / en boucle), car elleif
est souvent enseignée auparavantwhile
. Cependant, ce n'est pas vrai car cela signifierait unelse
blocage dans while-else serait exécuté à chaque fois que la condition est fausse.Pour faciliter votre compréhension, pensez-y de cette façon:
Une autre note:
la source
On pourrait y penser comme,
else
comme dans le reste des trucs, ou les autres trucs, qui n'ont pas été faits en boucle.la source
"else" ici est incroyablement simple, signifie simplement
1, "si
for clause
est terminé"Il est difficile d'écrire des instructions aussi longues que "la clause for est terminée", donc ils introduisent "else".
else
voici un si dans sa nature.2, cependant, que diriez-vous
for clause is not run at all
Il est donc complètement énoncé est une combinaison logique:
ou dites-le de cette façon:
ou de cette façon:
la source
Voici un autre cas d'utilisation idiomatique en plus de la recherche. Supposons que vous vouliez attendre qu'une condition soit vraie, par exemple un port à ouvrir sur un serveur distant, avec un certain délai d'expiration. Ensuite, vous pouvez utiliser une
while...else
construction comme ceci:la source
J'essayais juste de retrouver le sens moi-même. J'ai trouvé que ce qui suit aide!
• Considérez le
else
comme étant couplé avec l'if
intérieur de la boucle (au lieu de lefor
) - si la condition est remplie, rompez la boucle, sinon faites cela - sauf que c'est unelse
couplé avec plusieursif
s!• Si aucune
if
réponse n'a été satisfaite, faites-leelse
.• Les multiples
if
s peuvent également être considérés comme desif
-elif
s!la source
Je considère la structure comme pour (if) A else B, et pour (if) -else est un if-else spécial , grosso modo . Cela peut aider à comprendre autre chose .
A et B sont exécutés au plus une fois, ce qui est identique à la structure if-else.
for (if) peut être considéré comme un if spécial, qui effectue une boucle pour essayer de remplir la condition if. Une fois la condition if remplie, A et break ; Sinon , B.
la source
Python utilise une boucle else for et while pour que si rien ne s'applique à la boucle, il se passe autre chose. Par exemple:
La sortie serait «Salut» encore et encore (si j'ai raison).
la source