Dado o seguinte código (que não funciona):
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 uma maneira de fazer isso funcionar? Ou devo fazer uma verificação para interromper o loop de entrada e, em seguida, outra verificação mais limitada no loop externo para interromper todos juntos, se o usuário estiver satisfeito?
python
nested-loops
break
control-flow
Matthew Scharley
fonte
fonte
goto
se você estiver aninhado em muitos loops #Respostas:
Meu primeiro instinto seria refatorar o loop aninhado em uma função e usá-lo
return
para sair.fonte
return
é a abordagem correta. E o raciocínio é que, de acordo com o Zen de Python , "flat é melhor que aninhado". Temos três níveis de aninhamento aqui e, se isso começar a atrapalhar, é hora de reduzir o aninhamento ou, pelo menos, extrair todo o aninhamento para uma função própria.Aqui está outra abordagem que é curta. A desvantagem é que você só pode quebrar o loop externo, mas às vezes é exatamente o que você deseja.
Isso usa a construção for / else explicada em: Por que o python usa 'else' depois dos loops for e while?
Informações principais: parece que o loop externo sempre quebra. Mas se o loop interno não quebrar, o loop externo também não.
A
continue
afirmação é a mágica aqui. Está na cláusula for-else. Por definição, isso acontece se não houver interrupção interna. Nessa situação,continue
evita-se a ruptura externa.fonte
O PEP 3136 propõe quebras / continue rotuladas. Guido o rejeitou porque "código tão complicado para exigir esse recurso é muito raro". O PEP menciona algumas soluções alternativas (como a técnica de exceção), enquanto Guido considera que a refatoração para usar o retorno será mais simples na maioria dos casos.
fonte
return
geralmente seja o caminho a percorrer, já vi alguns casos em que uma simplesbreak 2
declaração concisa ' ' faria tanto sentido. Além disso, refatorar /return
não funciona da mesma maneiracontinue
. Nesses casos, a quebra numérica e a continuação seriam mais fáceis de seguir e menos confusas do que refatorar para uma função minúscula, gerar exceções ou lógica complicada envolvendo a configuração de um sinalizador para quebrar em cada nível de ninho. É uma pena que Guido tenha rejeitado.break; break
seria bom.break
todos os loops. Estúpido.Primeiro, a lógica comum é útil.
Se, por algum motivo, as condições de encerramento não puderem ser resolvidas, as exceções são um plano de retorno.
Para este exemplo específico, uma exceção pode não ser necessária.
Por outro lado, geralmente temos as opções "Y", "N" e "Q" nos aplicativos de modo caractere. Para a opção "Q", queremos uma saída imediata. Isso é mais excepcional.
fonte
done
). (2) levantando uma exceção. Mesclá-los em uma única solução apenas faz com que pareça complicado. Para futuros leitores: UTILIZE todas as linhas que envolvemdone
OU definemGetOutOfLoop(Exception)
e aumentam / exceto isso.Exception
construtor (por exemploraise Exception('bla bla bla')
) são válidas no Python 2 e no Python 3. O primeiro é preferível nesse caso, porque não queremos nossoexcept
bloco para capturar todas as exceções, mas apenas a exceção especial que estamos usando para sair do loop. Se fizermos as coisas da maneira que você sugere e, em seguida, um bug em nosso código fizer com que uma exceção inesperada seja levantada, ela será tratada incorretamente da mesma forma que sair deliberadamente do loop.Costumo concordar que a refatoração em uma função geralmente é a melhor abordagem para esse tipo de situação, mas para quando você realmente precisa interromper os loops aninhados, aqui está uma variante interessante da abordagem de geração de exceção descrita pela @ S.Lott. Ele usa a
with
declaração do Python para tornar a criação de exceção um pouco melhor. Defina um novo gerenciador de contexto (você só precisa fazer isso uma vez) com:Agora você pode usar este gerenciador de contexto da seguinte maneira:
Vantagens: (1) é um pouco mais limpo (sem tentativa explícita, exceto bloco) e (2) você obtém uma
Exception
subclasse personalizada para cada uso denested_break
; não é necessário declarar sua própriaException
subclasse a cada vez.fonte
Primeiro, você também pode considerar tornar o processo de obtenção e validação da entrada uma função; dentro dessa função, você pode simplesmente retornar o valor se o seu correto, e mantê-fiação no enquanto loop se não. Isso evita essencialmente o problema que você resolveu e geralmente pode ser aplicado no caso mais geral (quebra de vários loops). Se você absolutamente deve manter essa estrutura em seu código e realmente não deseja lidar com os booleanos da contabilidade ...
Você também pode usar goto da seguinte maneira (usando um módulo April Fools daqui ):
Eu sei, eu sei, "você não usará goto" e tudo mais, mas funciona bem em casos estranhos como este.
fonte
Introduzir uma nova variável que você usará como um 'disjuntor'. Primeiro atribua algo a ele (Falso, 0, etc.) e, em seguida, dentro do loop externo, antes de sair dele, altere o valor para outra coisa (True, 1, ...). Depois que o loop sair, faça o loop 'pai' verificar esse valor. Deixe-me demonstrar:
Se você tem um loop infinito, esta é a única saída; para outros loops, a execução é realmente muito mais rápida. Isso também funciona se você tiver muitos loops aninhados. Você pode sair de todos, ou apenas alguns. Infinitas possibilidades! Espero que isso tenha ajudado!
fonte
Para interromper vários loops aninhados, sem refatorar em uma função, use uma "instrução goto simulada" com a exceção StopIteration interna :
Consulte esta discussão sobre o uso de instruções goto para interromper loops aninhados.
fonte
ou algo assim. Você pode definir uma variável no loop interno e verificá-la no loop externo imediatamente após a saída do loop interno, quebrando, se apropriado. Eu meio que gosto do método GOTO, desde que você não se importe em usar o módulo de piadas do April Fool - não é Pythonic, mas faz sentido.
fonte
Esta não é a maneira mais bonita de fazer isso, mas na minha opinião, é a melhor maneira.
Tenho certeza de que você poderia descobrir algo usando recursão aqui também, mas não sei se essa é uma boa opção para você.
fonte
E por que não continuar repetindo se duas condições são verdadeiras? Eu acho que essa é uma maneira mais pitônica:
Não é?
Muito bem sucedida.
fonte
while dejaVu:
? Você define como verdadeiro de qualquer maneira.True
condições para pular dois loops, mas apenas um é suficiente.if not dejaVu: break
na parte inferior e, assim, sair do loop principal? Eu acho que a solução está mais próxima do que foi solicitado. +1Fatore sua lógica de loop em um iterador que produz as variáveis de loop e retorna quando concluído - aqui está uma simples que expõe imagens em linhas / colunas até ficarmos sem imagens ou fora de locais para colocá-las:
Isso tem a vantagem de dividir a lógica complicada do loop e o processamento ...
fonte
Nesse caso, como apontado por outros, a decomposição funcional é o caminho a percorrer. Código em Python 3:
fonte
Existe um truque oculto na
while ... else
estrutura do Python que pode ser usado para simular a quebra dupla sem muitas alterações / adições de código. Em essência, se awhile
condição for falsa, oelse
bloco é acionado. Nenhuma exceçãocontinue
oubreak
acionar oelse
bloco. Para obter mais informações, consulte as respostas à " Cláusula Else no Python while statement " ou no documento Python while (v2.7) .A única desvantagem é que você precisa mover a condição de quebra dupla para a
while
condição (ou adicionar uma variável de flag). Variações disso também existem para ofor
loop, onde oelse
bloco é acionado após a conclusão do loop.fonte
How to break out of multiple loops in Python?
e a resposta deveria ter sido "Não funciona, tente outra coisa". Eu sei que isso corrige o exemplo exato do OP, mas não responde à pergunta deles.Outra maneira de reduzir sua iteração para um loop de nível único seria através do uso de geradores, como também especificado na referência python
Você pode escalá-lo para qualquer número de níveis para o loop
A desvantagem é que você não pode mais quebrar apenas um único nível. É tudo ou nada.
Outra desvantagem é que ele não funciona com um loop while. Originalmente, eu queria postar esta resposta no Python - `break` fora de todos os loops, mas infelizmente isso está fechado como uma duplicata deste
fonte
Minha razão para vir aqui é que eu tinha um loop externo e um loop interno da seguinte forma:
Como você pode ver, ele não vai realmente para o próximo x, mas para o próximo y.
o que eu encontrei para resolver isso era simplesmente executar o array duas vezes:
Sei que esse foi um caso específico da pergunta do OP, mas estou postando na esperança de que ajude alguém a pensar sobre seu problema de maneira diferente, mantendo as coisas simples.
fonte
break
vez decontinue
faria o que você deseja, não faria? :-)Tente usar um gerador infinito.
fonte
Usando uma função:
Tente executar os códigos acima comentando
return
também.Sem usar nenhuma função:
Agora, execute os códigos acima, como é o primeiro, e tente executar comentando cada linha que contém
break
uma de cada vez na parte inferior.fonte
Uma maneira fácil de transformar vários loops em um único loop quebrável é usar
numpy.ndindex
Você precisa indexar seus objetos, em vez de poder iterar os valores explicitamente, mas pelo menos em casos simples, parece ser aproximadamente 2-20 vezes mais simples do que a maioria das respostas sugeridas.
fonte
fonte
provavelmente um pequeno truque como abaixo fará se não preferir refatorar a função
adicionada 1 variável break_level para controlar a condição do loop while
fonte
Você pode definir uma variável (por exemplo, break_statement ) e alterá-la para um valor diferente quando ocorrer uma condição de duas interrupções e usá-la na instrução if para interromper também o segundo loop.
fonte
Gostaria de lembrá-lo que as funções no Python podem ser criadas bem no meio do código e podem acessar as variáveis circundantes de forma transparente para leitura e com
nonlocal
ouglobal
declaração para escrita.Portanto, você pode usar uma função como uma "estrutura de controle quebrável", definindo um local para o qual deseja retornar:
fonte
Soluções de 2 maneiras
Com um exemplo: essas duas matrizes são iguais / iguais?
matrix1 e matrix2 são do mesmo tamanho, n, 2 matrizes dimensionais.
Primeira solução , sem função
Segunda solução , com uma função
Esta é a solução final para o meu caso
Tenha um bom dia!
fonte
fonte
Espero que isso ajude:
fonte
Aqui está uma implementação que parece funcionar:
A única desvantagem é que você deve definir
break_
antes dos loops.fonte
O crédito vai para Vivek Nagarajan, programador desde 1987
Usando a Função
Usando sinalizador
fonte
Semelhante como o anterior, mas mais compacto. (Booleanos são apenas números)
fonte
Como essa pergunta se tornou uma pergunta padrão para quebrar um loop específico, eu gostaria de dar minha resposta com o exemplo usando
Exception
.Embora não exista um rótulo chamado quebra de loop na construção de loop multipolar, podemos usar exceções definidas pelo usuário para entrar em um loop específico de nossa escolha. Considere o exemplo a seguir, onde vamos imprimir todos os números de até 4 dígitos no sistema de numeração da base 6:
Quando imprimimos a saída, nunca obteremos nenhum valor cujo local da unidade seja com 4. Nesse caso, não quebramos nenhum loop, pois ele
BreakLoop(4)
é gerado e capturado no mesmo loop. Da mesma forma, sempre que dez lugares tiverem 3, entraremos no terceiro loop usandoBreakLoop(3)
. Sempre que cem lugares estão com 5, entramos no segundo loop usandoBreakLoop(2)
e sempre que o milésimo lugar está tendo 2, entramos no primeiro loop usandoBreakLoop(1)
.Em resumo, aumente sua Exceção (embutida ou definida pelo usuário) nos loops internos e pegue-a no loop de onde você deseja retomar o controle. Se você deseja interromper todos os loops, pegue a exceção fora de todos os loops. (Eu não mostrei este caso no exemplo).
fonte