Étant donné le code suivant (qui ne fonctionne pas):
while True:
#snip: print out current state
while True:
ok = get_input("Is this ok? (y/n)")
if ok.lower() == "y": break 2 #this doesn't work :(
if ok.lower() == "n": break
#do more processing with menus and stuff
Existe-t-il un moyen de faire fonctionner cela? Ou dois-je faire une vérification pour sortir de la boucle d'entrée, puis une autre, plus limitée, vérifier la boucle extérieure pour sortir toutes ensemble si l'utilisateur est satisfait?
python
nested-loops
break
control-flow
Matthew Scharley
la source
la source
goto
si vous êtes niché au fond de beaucoup de bouclesRéponses:
Mon premier réflexe serait de refactoriser la boucle imbriquée en fonction et de l'utiliser
return
pour sortir.la source
return
est la bonne approche. Et le raisonnement est que, selon le Zen de Python , "plat est meilleur que imbriqué". Nous avons trois niveaux d'imbrication ici et si cela commence à gêner, il est temps de réduire l'imbrication ou au moins d'extraire toute l'imbrication dans une fonction qui lui est propre.Voici une autre approche courte. L'inconvénient est que vous ne pouvez rompre que la boucle externe, mais parfois c'est exactement ce que vous voulez.
Ceci utilise la construction for / else expliquée à: Pourquoi python utilise 'else' après les boucles for et while?
Aperçu: il semble que la boucle externe se brise toujours. Mais si la boucle intérieure ne se rompt pas, la boucle extérieure non plus.
La
continue
déclaration est la magie ici. C'est dans la clause for-else. Par définition, cela se produit s'il n'y a pas de rupture intérieure. Dans cette situation,continue
contourne proprement la coupure extérieure.la source
Le PEP 3136 propose la mention pause / continuer. Guido l'a rejeté car "le code si compliqué d'exiger cette fonctionnalité est très rare". Le PEP mentionne cependant quelques solutions de contournement (telles que la technique d'exception), tandis que Guido pense que la refactorisation pour utiliser le retour sera plus simple dans la plupart des cas.
la source
return
soit généralement la voie à suivre, j'ai vu pas mal de cas où une simplebreak 2
déclaration concise ' ' aurait tellement de sens. De plus, refactor /return
ne fonctionne pas de la même manièrecontinue
. Dans ces cas, la rupture et la poursuite numériques seraient plus faciles à suivre et moins encombrées que la refactorisation vers une fonction minuscule, levant des exceptions ou une logique alambiquée impliquant la définition d'un indicateur pour qu'il se casse à chaque niveau d'imbrication. C'est dommage que Guido l'ait rejeté.break; break
serait bien.break
toutes les boucles. Stupide.Premièrement, la logique ordinaire est utile.
Si, pour une raison quelconque, les conditions de résiliation ne peuvent pas être définies, les exceptions sont un plan de secours.
Pour cet exemple spécifique, une exception peut ne pas être nécessaire.
D'un autre côté, nous avons souvent des options "Y", "N" et "Q" dans les applications en mode caractère. Pour l'option "Q", nous voulons une sortie immédiate. C'est plus exceptionnel.
la source
done
). (2) levant une exception. Les fusionner en une seule solution rend tout simplement compliqué. Pour les futurs lecteurs: Soit utiliser toutes les lignes impliquantdone
, OU définirGetOutOfLoop(Exception)
et augmenter / sauf cela.Exception
constructeur (par exempleraise Exception('bla bla bla')
) sont valides à la fois dans Python 2 et Python 3. La première est préférable dans ce cas parce que nous ne voulons pas notreexcept
bloc pour intercepter toutes les exceptions, mais uniquement l'exception spéciale que nous utilisons pour quitter la boucle. Si nous faisons les choses comme vous le suggérez, puis qu'un bogue dans notre code provoque une exception inattendue, il sera traité à tort de la même manière que la fermeture délibérée de la boucle.J'ai tendance à convenir que la refactorisation dans une fonction est généralement la meilleure approche pour ce genre de situation, mais lorsque vous avez vraiment besoin de sortir de boucles imbriquées, voici une variante intéressante de l'approche de levée d'exceptions décrite par @ S.Lott. Il utilise l'
with
instruction de Python pour rendre la levée d'exceptions un peu plus agréable. Définissez un nouveau gestionnaire de contexte (vous ne devez le faire qu'une seule fois) avec:Vous pouvez maintenant utiliser ce gestionnaire de contexte comme suit:
Avantages: (1) il est légèrement plus propre (pas de bloc try-except explicite), et (2) vous obtenez une
Exception
sous - classe personnalisée pour chaque utilisation denested_break
; pas besoin de déclarer votre propreException
sous-classe à chaque fois.la source
Tout d'abord, vous pouvez également envisager de faire du processus d'obtention et de validation de l'entrée une fonction; dans cette fonction, vous pouvez simplement renvoyer la valeur si elle est correcte, et continuer à tourner dans le temps en boucle sinon. Cela évite essentiellement le problème que vous avez résolu et peut généralement être appliqué dans le cas plus général (rupture de plusieurs boucles). Si vous devez absolument conserver cette structure dans votre code et que vous ne voulez vraiment pas vous occuper des booléens de comptabilité ...
Vous pouvez également utiliser goto de la manière suivante (en utilisant un module April Fools à partir d' ici ):
Je sais, je sais, "tu n'utiliseras pas goto" et tout ça, mais ça marche bien dans des cas étranges comme celui-ci.
la source
Introduisez une nouvelle variable que vous utiliserez comme «disjoncteur de boucle». Attribuez-lui d'abord quelque chose (False, 0, etc.), puis, à l'intérieur de la boucle externe, avant de vous en séparer, changez la valeur en quelque chose d'autre (True, 1, ...). Une fois la boucle terminée, vérifiez la valeur de la boucle «parent». Permettez-moi de démontrer:
Si vous avez une boucle infinie, c'est la seule issue; pour les autres boucles, l'exécution est vraiment beaucoup plus rapide. Cela fonctionne également si vous avez plusieurs boucles imbriquées. Vous pouvez quitter tout ou quelques-uns. Possibilités infinies! J'espère que cela vous a aidé!
la source
Pour sortir de plusieurs boucles imbriquées, sans refactorisation dans une fonction, utilisez une "instruction goto simulée" avec l' exception StopIteration intégrée :
Voir cette discussion sur l'utilisation des instructions goto pour sortir des boucles imbriquées.
la source
ou quelque chose comme ça. Vous pouvez définir une variable dans la boucle interne et la vérifier dans la boucle externe immédiatement après la sortie de la boucle interne, en la cassant si nécessaire. J'aime un peu la méthode GOTO, à condition que cela ne vous dérange pas d'utiliser un module de blague de April Fool - ce n'est pas Pythonic, mais cela a du sens.
la source
Ce n'est pas la plus jolie façon de le faire, mais à mon avis, c'est la meilleure façon.
Je suis presque sûr que vous pourriez également trouver quelque chose en utilisant la récursivité, mais je ne sais pas si c'est une bonne option pour vous.
la source
Et pourquoi ne pas continuer à boucler si deux conditions sont vraies? Je pense que c'est une manière plus pythonique:
N'est-ce pas?
Bonne chance.
la source
while dejaVu:
? Vous le définissez de toute façon.True
conditions à sauter deux boucles, mais une seule suffit.if not dejaVu: break
en bas et quitter ainsi la boucle principale? Je pense que la solution est la plus proche de ce qui a été demandé. +1Factorisez votre logique de boucle dans un itérateur qui produit les variables de boucle et retourne une fois terminé - en voici une simple qui dispose les images en lignes / colonnes jusqu'à ce que nous soyons à court d'images ou hors d'endroits pour les mettre:
Cela a l'avantage de diviser la logique de boucle compliquée et le traitement ...
la source
Dans ce cas, comme d'autres l'ont également souligné, la décomposition fonctionnelle est la voie à suivre. Code en Python 3:
la source
Il existe une astuce cachée dans la
while ... else
structure Python qui peut être utilisée pour simuler la double coupure sans beaucoup de changements / ajouts de code. En substance, si lawhile
condition est fausse, leelse
blocage est déclenché. Ni exception,continue
nibreak
déclenchement duelse
blocage. Pour plus d'informations, voir les réponses à la " clause Else sur l'instruction Python while " ou la documentation Python sur while (v2.7) .Le seul inconvénient est que vous devez déplacer la double condition de rupture dans la
while
condition (ou ajouter une variable d'indicateur). Il existe également des variations pour lafor
boucle, où leelse
bloc est déclenché après l'achèvement de la boucle.la source
How to break out of multiple loops in Python?
et la réponse aurait dû être "Cela ne fonctionne pas, essayez autre chose". Je sais que cela corrige l'exemple exact donné de l'OP, mais ne répond pas à leur question.Une autre façon de réduire votre itération à une boucle à un seul niveau serait d'utiliser des générateurs comme spécifié également dans la référence python
Vous pouvez l'adapter à n'importe quel nombre de niveaux pour la boucle
L'inconvénient est que vous ne pouvez plus casser un seul niveau. C'est tout ou rien.
Un autre inconvénient est qu'il ne fonctionne pas avec une boucle while. À l'origine, je voulais publier cette réponse sur Python - "sortir" de toutes les boucles, mais malheureusement, c'est fermé en double de celui-ci
la source
Ma raison d'être ici est que j'avais une boucle externe et une boucle interne comme ceci:
Comme vous pouvez le voir, il ne passera pas au x suivant, mais passera au y suivant à la place.
ce que j'ai trouvé pour résoudre ce problème était simplement de parcourir le tableau deux fois à la place:
Je sais que c'était un cas spécifique de la question d'OP, mais je le poste dans l'espoir que cela aidera quelqu'un à penser son problème différemment tout en gardant les choses simples.
la source
break
au lieu decontinue
ferait ce que vous voulez, non? :-)Essayez d'utiliser un générateur infini.
la source
En utilisant une fonction:
Essayez d'exécuter les codes ci-dessus en les commentant
return
également.Sans utiliser aucune fonction:
Maintenant, exécutez les codes ci-dessus tels quels, puis essayez de les exécuter en commentant chaque ligne contenant
break
une à la fois à partir du bas.la source
Un moyen facile de transformer plusieurs boucles en une seule boucle cassable consiste à utiliser
numpy.ndindex
Vous devez indexer dans vos objets, au lieu de pouvoir parcourir les valeurs explicitement, mais au moins dans les cas simples, cela semble être environ 2-20 fois plus simple que la plupart des réponses suggérées.
la source
la source
probablement peu de truc comme ci-dessous fera sinon préfère refactoriel en fonction
ajout d'une variable break_level pour contrôler la condition de la boucle while
la source
Vous pouvez définir une variable (par exemple break_statement ), puis la changer en une valeur différente lorsque la condition à deux ruptures se produit et l'utiliser dans l'instruction if pour rompre également à partir de la deuxième boucle.
la source
Je voudrais vous rappeler que les fonctions en Python peuvent être créées en plein milieu du code et peuvent accéder aux variables environnantes de manière transparente pour la lecture et avec
nonlocal
ouglobal
déclaration pour l'écriture.Vous pouvez donc utiliser une fonction comme une "structure de contrôle cassable", définissant un endroit où vous souhaitez revenir:
la source
Solutions de 2 façons
Avec un exemple: ces deux matrices sont-elles égales / identiques?
matrice1 et matrice2 sont de même taille, n, 2 matrices dimensionnelles.
Première solution , sans fonction
Deuxième solution , avec une fonction
C'est la solution finale pour mon cas
Bonne journée!
la source
la source
Espérons que cela aide:
la source
Voici une implémentation qui semble fonctionner:
Le seul inconvénient est que vous devez définir
break_
avant les boucles.la source
Le mérite revient à Vivek Nagarajan, programmeur depuis 1987
Utilisation de la fonction
Utilisation du drapeau
la source
Similaire à la précédente, mais plus compact. (Les booléens ne sont que des nombres)
la source
Puisque cette question est devenue une question standard pour pénétrer dans une boucle particulière, je voudrais donner ma réponse avec un exemple en utilisant
Exception
.Bien qu'il n'existe aucune étiquette nommée rupture de boucle dans une construction en boucle multipale, nous pouvons utiliser des exceptions définies par l'utilisateur pour pénétrer dans une boucle particulière de notre choix. Prenons l'exemple suivant où imprimons tous les nombres jusqu'à 4 chiffres dans le système de numérotation base-6:
Lorsque nous imprimons la sortie, nous n'obtiendrons jamais de valeur dont la place unitaire est à 4. Dans ce cas, nous ne nous séparons d'aucune boucle car elle
BreakLoop(4)
est élevée et prise dans la même boucle. De même, chaque fois que dix places ont 3, nous entrons dans la troisième boucle en utilisantBreakLoop(3)
. Chaque fois que cent lieux ont 5, nous entrons dans la deuxième boucle en utilisantBreakLoop(2)
et chaque fois que les mille lieux en ont 2, nous entrons dans la première boucle en utilisantBreakLoop(1)
.En bref, augmentez votre exception (intégrée ou définie par l'utilisateur) dans les boucles internes et interceptez-la dans la boucle à partir de laquelle vous souhaitez reprendre votre contrôle. Si vous souhaitez interrompre toutes les boucles, interceptez l'exception en dehors de toutes les boucles. (Je n'ai pas montré ce cas dans l'exemple).
la source