Comment puis-je donner du sens de l ` "autre" clause de Python boucles?
De nombreux Python pour les programmeurs sont probablement pas au courant que la syntaxe de while
boucles et for
boucles comprend une option de else:
clause:
for val in iterable:
do_something(val)
else:
clean_up()
Le corps de la else
clause est une bonne place pour certains types de nettoyage des actions, et est exécuté sur l'arrêt normal de la boucle: I. e., la sortie de la boucle avec return
ou break
ignore le else
clause; quitter après un continue
l'exécute. Je sais ce que parce que je viens de regardé (encore une fois), parce que je ne me souviens jamais quand la else
clause est exécutée.
Toujours? Sur "l'échec" de la boucle, comme le nom le suggère? Régulière de la résiliation? Même si la boucle est sortie avec return
? Je ne pouvez jamais être certain que sans le regarder.
Je blâme mon persistance de l'incertitude sur le choix du mot-clé: je trouve else
incroyablement unmnemonic pour cette sémantique. Ma question n'est pas "pourquoi est-ce le mot-clé utilisé à cette fin" (ce qui je ne serais probablement voter pour le fermer, mais seulement après avoir lu les réponses et les commentaires), mais comment puis-je penser à la else
mot-clé, de sorte que sa sémantique logique, et je peut donc s'en souvenir?
Je suis sûr qu'il y a une bonne quantité de discussion à ce sujet, et je peux imaginer que le choix a été fait pour des raisons de cohérence avec le try
de l'instruction else:
de l'alinéa (que j'ai aussi de regarder en haut), et avec l'objectif de ne pas ajouter à la liste de Python mots réservés. Peut-être les raisons du choix de else
permettra de clarifier sa fonction et de le rendre plus mémorable, mais je suis après le raccordement du nom de la fonction, non pas après une explication historique en soi.
Les réponses à cette question, qui à ma question a été brièvement fermé comme un doublon, contiennent beaucoup d'histoire. Ma question a un accent différent (comment connecter la une sémantique spécifique de else
avec le mot-clé le choix), mais je pense qu'il devrait y avoir un lien à cette question quelque part.
- Comment au sujet de "si il y a quelque chose à gauche pour effectuer une itération d'autre..."
- Wow, ça a été rapide. Le focus de la question est à peu près ce que je ne voulais pas demander, comme je l'explique dans ma question), mais je vais prendre "si trouvé ... sinon:" comme une interprétation.
- c'est sans doute proche de la marque, mais ça va être une mauvaise chose si la boucle est en train de vérifier pour les expressions du FOLKLORE en le comparant à une chaîne vide (comme beaucoup le font).
- Je pense que vous vous en souvenez maintenant, après l'écriture de cette question 🙂
- Je pensais la même chose! 🙂 Je vais le savoir dans une couple de semaines, je suppose...
- pourquoi voudriez-vous rappelez-vous un difficile à retenir, caractéristique rare si vous pouvez google en 10 secondes?
- le
else
qui signifie en gros, "si la poursuite de la condition d'échec". Dans un cadre traditionnel pour la boucle, la poursuite de la condition est généralementi < 42
, dans ce cas, vous pouvez voir que la partie queif i < 42; execute the loop body; else; do that other thing
- C'est tout à fait vrai, et j'aime particulièrement drawoc réponse, mais une autre chose à considérer est que else est une clé qui le rend aussi un peu de bon sens syntaxically. Vous savez peut-être essayer/sauf peut-être essayer/sauf/enfin, mais il a également else - exécuter ce code si aucune exception n'est arrivé. Qui est btw, pas la même chose que de bousculer ce code sous le coup d'essayer clause - la gestion des exceptions est meilleure si étroitement ciblée. Donc, si elle n'est conceptuel de sens que par un certain nombre de réponses ici - je pense que c'est le mot clé de la réutilisation à jouer trop exécuter ce sous certaines conditions.
- Mon esprit est soufflé par ce parce que j'ai souvent voulu cela pour le reste de construire en Java. Maintenant je trouver qu'il existe déjà, avec la sémantique exacte j'ai toujours voulu, mais en Python? Et c'est exactement le genre de gentil, mais en fin de compte inutile truc que la conception par le comité de langues comme Java ne sera jamais ajouter. Oh bien.
- Je crois me souvenir que Perl a aussi quelque chose comme ça. Les mêmes mots-clés utilisés pour modifier une boucle for dans le corps (continuer, pause), sont également utilisés pour le suffixe consolidés. Je ne me souviens pas des détails seulement que c'est différent de la façon dont les mots clés sont utilisés dans C.
- cela pourrait être: Comme je l'ai depuis découvert, "le pour/le reste de construire a été conçu par Donald Knuth comme un remplacement pour certaines goto.. Knuth utilisé
else
, et il fait sens à la fois en raison de la façon dont le bouclage a été fait avant que la boucle de contrôle des états. - Mais peut-être que vous êtes en train de penser de perl postfix
if
, qui peut aller après quelque chose, par exemplebreak if $var;
,print "Found it!" if $found;
, etc. - Non, ce n'est pas ce à quoi je pensais. Voir ici.
- Hmm, je ne pense pas que je savais à propos de cette fonctionnalité particulière (il semble que la date à partir de 2011). Il est différent de
break
, comme il est exécuté à plusieurs reprises. Pourtant, une autre extension classique de boucles, et probablement destiné à l'oubli comme les autres... (Guido mentionnés que s'il avait à refaire, il ne serait pas fournir la boucle-d'autre fonctionnalité en python sous n'importe quel nom.) - pardon pour mon (probablement stupide) de la question, mais comment exactement de la fonctionnalité utile à tous? N'est-ce pas
for val in iterable: { do_something(val) } else: { clean_up() }
exactement le même quefor val in iterable: { do_something(val) } clean_up()
(j'ai dû mettre des accolades à la place des sauts de ligne, parce que je ne sais pas comment les ajouter dans un commentaire) - il y a une différence lorsque le code est fermé par
break
. L'canonique de cas d'utilisation, c'est quand la boucle recherches pour quelque chose, et se casse quand il le trouve. Leelse
n'est exécutée que si rien n'est trouvé. - Très pertinent: python-notes.curiousefficiency.org/en/latest/python_concepts/...
Vous devez vous connecter pour publier un commentaire.
(Ce qui est inspirée par @Mark Tolonen de la réponse.)
Un
if
instruction s'exécute seselse
clause si sa condition est false.De manière identique, un
while
boucle s'exécute la clause else si sa condition est false.Cette règle correspond au comportement que vous avez décrit:
break
déclaration, vous sortir de la boucle sans évaluation de la condition, de sorte que la condition ne peut pas évaluer de faux et vous ne faites jamais fonctionner la clause else.continue
déclaration, vous l'évaluation de l'état de nouveau, et faire exactement ce que vous le feriez normalement au début d'une itération de boucle.Donc, si la condition est vraie, vous gardez en boucle, mais si il est faux d'exécuter la clause else.
return
, ne permettent pas d'évaluer l'état et, par conséquent, de ne pas exécuter la clause else.for
boucles se comportent de la même manière. Il suffit de considérer l'état comme vrai si l'itérateur a plus d'éléments, ou false sinon.elif
consolidés. Il y a réponse qui ne, et il a une nette upvote.break
s, auquel cas leelse
ne serait pas exécuté, mais la condition est Fausse. De la même façon avecfor
boucles elle peutbreak
sur le dernier élément.Mieux de penser à elle de cette façon: Le
else
bloc toujours être exécutée si tout va droit dans le précédentfor
bloc à ce qu'elle arrive à épuisement.Droit dans ce contexte, personne ne
exception
, pas debreak
, pas dereturn
. Toute déclaration qui détourne le contrôle defor
sera la cause de laelse
bloc pour être contourné.Une commune de cas d'utilisation est trouvé lors de la recherche d'un élément dans un
iterable
, pour qui la recherche est soit appelé à l'arrêt lorsque l'élément est trouvé ou un"not found"
drapeau est hissé/imprimé par la suiteelse
bloc:Un
continue
ne pas détourner le contrôle defor
, de sorte que le contrôle de procéder à laelse
après lafor
est épuisé.else
clause doit être exécuté quand les choses ne pas aller à droite, n'est-ce pas? Je suis déjà en train de se confondre à nouveau...else
]", depuis leelse
est exécuté lorsque aucune des conditions de la boucle for True, comme je viens de le démontrer dans ma réponseFalse
. Donc, la question de la façon dont lefor
est cassé dépend du cas d'utilisation.else
en python). Vous fournir une bonne intuition résumé de ceelse
n', @Moïse, mais pas de la façon dont on pourrait associer ce comportement avec "autre chose". Si un autre mot-clé a été utilisé (par exemple,nobreak
comme indiqué dans le cette réponse pour une question connexe), il serait plus facile à comprendre.else
, je pense que nous aurons à accepter le statu quo 🙂else
ne se comportent pas de la façon dont il sonne. Et pour le comprendre, vous devrez appliquer un peu d'abstraction, comme lenobreak
tout le monde a déjà été proposée.if
/while
condition prend la valeur false oufor
est hors d'éléments.break
existe le contenant de la boucle (après laelse
).continue
va et évalue la condition de la boucle de nouveau.if/elif
s la seule façon debreak
de la chaîne est l'une des conditions pour êtreTrue
, où comme d'une boucle for est arrêté avec l'explicitebreak
(et les deux sont cassés parreturn
ou exception) certes, je ne pense pas que des choses "mal" lorsque la boucle for doit briser.Quand un
if
exécuter uneelse
? Lors de sa condition est fausse. C'est exactement le même pour lawhile
/else
. Ainsi, vous pouvez penser dewhile
/else
comme unif
qui maintient l'exécution de sa véritable condition, jusqu'à ce qu'elle renvoie la valeur faux. Unbreak
ne change pas. Il saute de l'contenant boucle avec aucune évaluation. Leelse
est exécuté seulement si l'évaluation laif
/while
condition est fausse.La
for
est similaire, à l'exception de ses fausses condition est épuisant son itérateur.continue
etbreak
ne pas exécuterelse
. Ce n'est pas leur fonction. Lebreak
quitte le contenant de la boucle. Lecontinue
remonte vers le haut de la boucle, où la condition de la boucle est évaluée. C'est l'acte de l'évaluation deif
/while
false (oufor
n'a pas plus d'éléments) qui s'exécuteelse
et pas d'autre moyen.else
clause est exécuté que si la boucle est sortie aveccontinue
(ou normalement), mais pas si nous quitter avecbreak
. Ces subtilités sont la raison pour laquelle je suis en train de vraiment analyser ce queelse
captures et ce qu'il ne l'est pas.C'est ce qu'il signifie essentiellement:
C'est une jolie manière de l'écriture de ce modèle commun:
La
else
clause ne sera pas exécutée si il y a unreturn
parce quereturn
quitte la fonction, comme il le devrait. La seule exception à ce que vous pourriez penser estfinally
, dont le but est d'être sûr que c'est toujours exécuté.continue
a rien de spécial à voir avec cette affaire. Il provoque l'itération courante de la boucle à la fin de ce qui peut se produire à la fin de la totalité de la boucle, et clairement, dans ce cas, la boucle n'était pas terminé par unbreak
.try/else
est similaire:Si vous pensez à votre boucle comme une structure similaire à ceci (un peu de pseudo-code):
il pourrait faire un peu plus de sens. Une boucle est essentiellement juste un
if
instruction est répétée jusqu'à ce que la condition estfalse
. Et c'est le point important. La boucle vérifie son état et voit que c'estfalse
, ainsi exécute laelse
(tout comme un normalif/else
) et puis la boucle est terminée.Donc d'avis que le
else
seulement est exécutée lorsque la condition est vérifiée. Cela signifie que si vous quittez le corps de la boucle dans le milieu de l'exécution avec par exemple unreturn
ou unbreak
, puisque la condition n'est pas vérifié à nouveau, leelse
cas ne sera pas exécutée.Un
continue
sur l'autre main, elle arrête l'exécution, puis saute en arrière pour vérifier l'état de la boucle de nouveau, c'est pourquoi laelse
peut être atteint dans ce scénario.end
étiquette et vient de mettre lagoto loop
à l'intérieur de laif
corps. Peut-être même hausser en mettant leif
sur la même ligne que l'étiquette, et soudain, elle ressemble beaucoup à l'original.Mon gotcha moment avec la boucle de
else
clause a été quand j'ai été en regardant un talk par Raymond Hettinger, qui a raconté une histoire sur la façon dont il pense qu'il devrait avoir été appelénobreak
. Regardez le code suivant, que pensez-vous qu'il ferait?Que voulez-vous deviner il fait? Eh bien, la partie qui dit
nobreak
aurait ne sera exécutée que si unbreak
déclaration n'était pas frapper dans la boucle.Habituellement, j'ai tendance à penser à une structure de boucle comme ceci:
À être un peu comme un nombre variable de
if/elif
états:Dans ce cas, le
else
déclaration sur la boucle fonctionne exactement comme leelse
déclaration sur la chaîne deelif
s, il s'exécute uniquement si aucune des conditions avant d'évaluer la valeur True. (ou la rupture d'exécution avecreturn
ou une exception) Si ma boucle ne correspond pas à cette spécification habituellement j'ai choisi de ne pas utiliserfor: else
pour la raison exacte que vous avez posté cette question: il est non-intuitive.D'autres l'ont déjà expliqué, la mécanique de
while/for...else
, et la Python 3 langue de référence a l'autorité de la définition (voir alors que et pour), mais c'est mon mnémonique personnel, FWIW. Je suppose que pour moi, l'essentiel a été de diviser cela en deux parties: l'une pour comprendre le sens de laelse
par rapport à la boucle conditionnelle, et pour la compréhension de la boucle de contrôle.Je trouve que c'est plus facile de commencer par comprendre
while...else
:La
for...else
mnémonique est fondamentalement la même:Dans les deux cas, la
else
partie est atteinte lorsqu'il n'y a plus d'éléments à traiter, et le dernier point a été traité d'une manière régulière (c'est à dire pas debreak
oureturn
). Uncontinue
retourne et voit si il y a plus d'éléments. Mon mnémonique de ces règles s'applique à la foiswhile
etfor
:– avec "loop back " pour commencer", qui signifie, évidemment, le début de la boucle où nous vérifier s'il y a plus d'éléments dans l'itératif, pour autant que la
else
est concerné,continue
vraiment joue aucun rôle.else
pourrait également être utilisé pour faire quelque chose quand vous êtes tout simplement fini avec tous les éléments. Exemples d'écrire une entrée de journal, la mise à jour d'une interface utilisateur, ou de signalisation certains autres processus que vous avez terminé. Rien, vraiment. Aussi, certains morceaux de code a le "succès" de cas à la fin avec unbreak
à l'intérieur de la boucle, et laelse
est utilisé pour traiter le "erreur" cas où vous n'avez pas trouvé tout point au cours de l'itération (peut-être que c'était ce que vous pensiez?).else
bloc, ou de suivre le résultat de l'utilisation d'autres moyens. J'ai fondamentalement d'accord, je dis juste que je ne sais pas comment les gens utilisent cette fonctionnalité et c'est pourquoi j'aimerais éviter de faire des hypothèses de savoir si le "else
poignées de succès scénario" ou la "else
poignées échec scénario" est la plus courante. Mais vous avez un bon point, donc commentaire upvoted!Dans Développement piloté par les tests (ATS), lors de l'utilisation de la La Transformation De Priorité Prémisse paradigme, vous le traitez de boucles comme une généralisation des instructions conditionnelles.
Cette approche combine bien avec cette syntaxe, si vous considérez que de simples
if/else
(pas deelif
) déclarations:généralise à:
bien.
Dans d'autres langues, TDD étapes à partir d'un seul cas à cas, avec des collections nécessitent plus de refactoring.
Voici un exemple de 8thlight blog:
Dans l'article lié à 8thlight blog, le retour de kata est considéré comme: l'ajout des sauts de ligne à cordes (le
s
variable dans les extraits ci-dessous) pour les adapter à une largeur (lalength
variable dans les extraits ci-dessous). A un moment, la mise en œuvre se présente comme suit (en Java):et le test suivant, qui, actuellement, ne parvient pas est:
Nous avons donc le code qui fonctionne de manière conditionnelle: lorsqu'une condition particulière est remplie, un saut de ligne est ajouté. Nous voulons améliorer le code pour gérer plusieurs sauts de ligne. La solution présentée dans l'article propose d'appliquer le (si->alors que) transformation, cependant, l'auteur fait un commentaire que:
ce qui oblige à faire plus de modifier le code dans le contexte d'un test en échec:
En TDD nous voulons écrire moins de code possible de faire des tests passent. Grâce à Python syntaxe de la transformation suivante est possible:
à partir de:
à:
La façon dont je le vois,
else:
se déclenche lors de l'itération après la fin de la boucle.Si vous
break
oureturn
ouraise
vous n'avez pas itérer-delà de la fin de la boucle, vous arrêter immédiatement, et donc laelse:
bloc ne fonctionne pas. Si vouscontinue
vous encore itérer-delà de la fin de la boucle, depuis continue de passe à l'itération suivante. Il n'a pas d'arrêt de la boucle.goto
le haut sur le succès.) Mais c'est une version plus courte du haut-voté réponse...Pense de la
else
clause comme étant la partie de la boucle de construire,break
des pauses hors de la boucle de construire entièrement, et donc ignore leelse
clause.Mais vraiment, mon mental mapping est simplement que c'est le 'structurés' version du modèle C/C++ pattern:
Donc quand je rencontre des
for...else
ou l'écrire moi-même, plutôt que de comprendre qu'il directement, je me mis à le traduire dans la compréhension de la structure et ensuite travailler sur les parties de la syntaxe de python carte à certaines parties du motif.(J'ai mis 'structurés' dans guillemets parce que la différence n'est pas de savoir si le code est structuré ou non, mais simplement de savoir si il ya des mots-clés et de la grammaire dédié à la structure particulière)
else
? Si vous parliez de l'done:
étiquette stand de proxy ouelse:
, je crois que vous avez exactement à l'envers.done:
étiquette. L'ensemble de la correspondance est, peut-être, mieux dit ainsi: Python a laelse
-sur-boucle de construire, de sorte que vous pouvez exprimer ce modèle de flux de contrôle sansgoto
.else
évite.La façon dont je pense, la clé est de considérer le sens de
continue
plutôt queelse
.Autres mots-clés que vous mentionnez sortir de la boucle (sortie anormale), tandis que
continue
ne le fait pas, il a juste ignore le reste du bloc de code à l'intérieur de la boucle. Le fait qu'il peut précéder la boucle de résiliation est accessoire: la résiliation est effectivement fait dans la voie normale par l'évaluation de la boucle de l'expression conditionnelle.Ensuite, vous avez juste besoin de se rappeler que la
else
clause est exécutée après la boucle de la résiliation.Si vous essayez de paire
else
avecfor
dans votre esprit, il peut être source de confusion. Je ne pense pas que le mot-cléelse
était un bon choix pour cette syntaxe, Mais si vous avez une paireelse
avecbreak
, vous pouvez le voir il fait réellement sens.Permettez-moi de le démontrer dans le langage humain.
else
est à peine utile si il n'y avait pasbreak
dans lefor
boucle de toute façon.