Muitos programadores de Python provavelmente não sabem que a sintaxe de while
loops e for
loops inclui uma else:
cláusula opcional :
for val in iterable:
do_something(val)
else:
clean_up()
O corpo da else
cláusula é um bom local para certos tipos de ações de limpeza e é executado na finalização normal do loop: return
Ou seja, sair do loop com ou break
ignorar a else
cláusula; saindo depois que um continue
executa. Só sei disso porque procurei (mais uma vez), porque nunca consigo me lembrar de quando a else
cláusula é executada.
Sempre? Em "falha" do loop, como o nome sugere? Em terminação regular? Mesmo se o loop for encerrado comreturn
? Eu nunca posso ter certeza absoluta sem procurar.
Eu culpo minha persistente incerteza pela escolha da palavra-chave: acho else
incrivelmente unmnemônico para essa semântica. Minha pergunta não é "por que essa palavra-chave é usada para esse fim" (que eu provavelmente votaria para fechar, embora apenas depois de ler as respostas e os comentários), mas como posso pensar sobre a else
palavra - chave para que sua semântica faça sentido? pode, portanto, lembrar?
Tenho certeza de que houve uma boa quantidade de discussão sobre isso, e posso imaginar que a escolha foi feita por consistência com a cláusula try
da declaração else:
(que eu também preciso procurar) e com o objetivo de não adicionar à lista de Palavras reservadas do Python. Talvez as razões para a escolha else
esclareçam sua função e a tornem mais memorável, mas estou depois de conectar o nome à função, não depois da explicação histórica em si.
As respostas a esta pergunta , que minha pergunta foi brevemente fechada como duplicata, contêm muitas histórias interessantes. Minha pergunta tem um foco diferente (como conectar a semântica específica da else
opção de palavra-chave), mas acho que deve haver um link para essa pergunta em algum lugar.
fonte
else
meios basicamente "se a condição de continuação falhar". Em um loop for tradicional, a condição de continuação é tipicamentei < 42
, nesse caso, você pode ver essa parte comoif i < 42; execute the loop body; else; do that other thing
break
. O caso de uso canônico é quando o loop procura por algo e é interrompido quando o encontra. Oelse
é executado apenas se nada for encontrado.Respostas:
(Isso é inspirado na resposta de @Mark Tolonen.)
Uma
if
instrução executa suaelse
cláusula se sua condição for avaliada como falsa. Identicamente, umwhile
loop executa a cláusula else se sua condição for avaliada como falsa.Esta regra corresponde ao comportamento que você descreveu:
break
instrução, você sai do loop sem avaliar a condição; portanto, a condição não pode ser avaliada como falsa e você nunca executa a cláusula else.continue
instrução, você avalia a condição novamente e faz exatamente o que faria normalmente no início de uma iteração de loop. Portanto, se a condição for verdadeira, você continua em loop, mas se for falsa, executa a cláusula else.return
, não avaliam a condição e, portanto, não executam a cláusula else.for
os loops se comportam da mesma maneira. Apenas considere a condição como verdadeira se o iterador tiver mais elementos, ou caso contrário, falso.fonte
elif
afirmações. Existe uma resposta que sim, e ela tem uma votação líquida.break
s; nesse caso, aelse
execução não seria executada, mas a condição é False. Da mesma forma comfor
loops, podebreak
no último elemento.Melhor pensar dessa maneira: o
else
bloco sempre será executado se tudo der certo nofor
bloco anterior , de forma a atingir a exaustão.Bem neste contexto, significa não
exception
, nãobreak
, nãoreturn
. Qualquer declaração que controla o seqüestrofor
fará com que oelse
bloco seja ignorado.Um caso de uso comum é encontrado ao procurar um item em um
iterable
, para o qual a pesquisa é desativada quando o item é encontrado ou um"not found"
sinalizador é levantado / impresso por meio do seguinteelse
bloco:A
continue
não seqüestra o controle defor
, portanto, o controle continuará para oelse
depois que ofor
esgotamento.fonte
else
cláusula fosse executada quando as coisas não derem certo, não é? Eu já estou ficando confuso de novo ...else
]", poiselse
é executado quando nenhuma das condições no loop for avaliada como True, como demonstro na minha respostaFalse
. Portanto, a questão de como o problemafor
está quebrado depende do caso de uso.else
python). Você fornece um bom resumo intuitivo do queelse
faz, @Moses, mas não de como podemos associar esse comportamento a "else". Se uma palavra-chave diferente fosse usada (por exemplo,nobreak
como mencionado nesta resposta a uma pergunta relacionada), seria mais fácil entender.if
/ éwhile
avaliada como falsa oufor
está sem itens.break
existe o loop que contém (após oelse
).continue
volta e avalia a condição do loop novamente.Quando um
if
executa umelse
? Quando sua condição é falsa. É exatamente o mesmo para owhile
/else
. Portanto, você pode pensar emwhile
/else
como apenas umif
que continua executando sua condição verdadeira até avaliar falso. Abreak
não muda isso. Ele simplesmente salta do loop que contém sem avaliação. Oelse
é executado apenas se a avaliação da condiçãoif
/while
for falsa.O
for
é semelhante, exceto que sua condição falsa está esgotando seu iterador.continue
ebreak
não executeelse
. Essa não é a função deles. Abreak
sai do loop contendo. Acontinue
volta para o topo do circuito que contém, em que a condição de ciclo é avaliada. É o ato de avaliarif
/while
para falso (oufor
não tem mais itens) que executaelse
e de nenhuma outra maneira.fonte
else
cláusula é executada se o loop for encerrado comcontinue
(ou normalmente), mas não se sairmos combreak
. Essas sutilezas são o motivo pelo qual estou tentando realmente entender o queelse
capta e o que não capta.Isto é o que significa essencialmente:
É uma maneira melhor de escrever esse padrão comum:
A
else
cláusula não será executada se houver umreturn
porquereturn
deixa a função, como deve. A única exceção àquilo em que você pode estar pensando éfinally
, cujo objetivo é garantir que ele seja sempre executado.continue
não tem nada de especial a ver com esse assunto. Isso faz com que a iteração atual do loop termine, o que pode acabar com o loop inteiro e, claramente, nesse caso, o loop não foi encerrado por abreak
.try/else
É similar:fonte
Se você pensa em seus loops como uma estrutura semelhante a esta (um pouco pseudo-código):
pode fazer um pouco mais de sentido. Um loop é essencialmente apenas uma
if
declaração que é repetida até que a condição sejafalse
. E este é o ponto importante. O loop verifica sua condição e vê que éfalse
, assim, executa oelse
(como um normalif/else
) e, em seguida, o loop é concluído.Portanto, observe que os
else
únicos get são executados quando a condição é verificada . Isso significa que, se você sair do corpo do loop no meio da execução com, por exemplo, areturn
ou abreak
, como a condição não é verificada novamente, oelse
caso não será executado.A,
continue
por outro lado, interrompe a execução atual e depois volta para verificar a condição do loop novamente, e é por isso queelse
pode ser alcançado nesse cenário.fonte
end
rótulo e apenas coloque ogoto loop
interior doif
corpo. Talvez até superado colocando oif
mesmo na linha do rótulo, e de repente se parece muito com o original.Meu momento decisivo com a
else
cláusula do loop foi quando eu estava assistindo uma palestra de Raymond Hettinger , que contou uma história sobre como ele achava que deveria ter sido chamadanobreak
. Dê uma olhada no código a seguir, o que você acha que ele faria?O que você acha que faz? Bem, a parte que diz
nobreak
apenas seria executada se umabreak
declaração não fosse atingida no loop.fonte
Normalmente, costumo pensar em uma estrutura de loop assim:
Para ser muito parecido com um número variável de
if/elif
instruções:Nesse caso, a
else
instrução no loop for funciona exatamente como aelse
instrução na cadeia deelif
s, somente é executada se nenhuma das condições antes de avaliar como True. (ou interrompa a execução comreturn
ou uma exceção) Se meu loop não se encaixa nessa especificação, geralmente opto por não usá-lofor: else
pelo motivo exato pelo qual você postou esta pergunta: não é intuitivo.fonte
Outros já explicaram a mecânica
while/for...else
e a referência da linguagem Python 3 tem a definição autorizada (veja enquanto e para ), mas aqui está o meu mnemônico pessoal, o FWIW. Eu acho que a chave para mim foi dividir isso em duas partes: uma para entender o significado doelse
em relação ao condicional do loop e outra para entender o controle do loop.Acho que é mais fácil começar entendendo
while...else
:O
for...else
mnemônico é basicamente o mesmo:Nos dois casos, a
else
peça é alcançada apenas quando não houver mais itens a serem processados e o último item foi processado de maneira regular (ou seja, sembreak
oureturn
). Acontinue
apenas volta e vê se há mais itens. Meu mnemônico para essas regras se aplica a amboswhile
efor
:- com "loop back to start", o que significa, obviamente, o início do loop, onde verificamos se há mais itens no iterável; no que diz respeito a ele
else
,continue
realmente não desempenha nenhum papel.fonte
else
pode ser usado para fazer algo quando você simplesmente terminar com todos os itens. Os exemplos incluem escrever uma entrada de log, atualizar uma interface do usuário ou sinalizar algum outro processo que você concluiu. Qualquer coisa, mesmo. Além disso, alguns trechos de código têm o final do caso "bem-sucedido" com umbreak
dentro do loop eelse
são usados para lidar com o caso "error", no qual você não encontrou nenhum item adequado durante a iteração (talvez fosse o que você estava pensando do?).else
bloco do loop ou acompanhar o resultado usando outros meios. Eu basicamente concordo, estou apenas dizendo que não sei como as pessoas usam esse recurso e, portanto, gostaria de evitar supor se oelse
cenário " lida com caso de sucesso" ou "else
lida com caso de sucesso" é mais comum. Mas você tem um bom argumento, então comente com voto positivo!No desenvolvimento orientado a teste (TDD), ao usar o paradigma Transformation Priority Premise , você trata os loops como uma generalização de instruções condicionais.
Essa abordagem combina bem com esta sintaxe, se você considerar apenas declarações simples
if/else
(nãoelif
):generaliza para:
agradável.
Em outros idiomas, as etapas TDD de um único caso para casos com coleções exigem mais refatoração.
Aqui está um exemplo do blog 8thlight :
No artigo vinculado no blog 8thlight, o kata de quebra automática de linha é considerado: adicionando quebras de linha às seqüências de caracteres (a
s
variável nos trechos abaixo) para ajustá-las a uma determinada largura (alength
variável nos trechos abaixo). Em um ponto, a implementação é a seguinte (Java):e o próximo teste que falhar atualmente é:
Portanto, temos um código que funciona condicionalmente: quando uma condição específica é atendida, uma quebra de linha é adicionada. Queremos melhorar o código para lidar com várias quebras de linha. A solução apresentada no artigo propõe aplicar a transformação (se-> enquanto) , no entanto, o autor faz um comentário que:
que força a fazer mais alterações no código no contexto de um teste com falha:
No TDD, queremos escrever o menos código possível para fazer os testes passarem. Graças à sintaxe do Python, é possível a seguinte transformação:
de:
para:
fonte
A meu ver,
else:
dispara quando você iterar além do final do loop.Se você
break
oureturn
ouraise
você não iterate após o final do loop, você parar immeadiately, e, portanto, oelse:
bloco não será executado. Se vocêcontinue
ainda iterar após o final do loop, pois continue apenas pula para a próxima iteração. Não para o loop.fonte
goto
topo em caso de sucesso.) Mas é uma versão mais curta do mais votados resposta ...Pense na
else
cláusula como parte da construção do loop;break
quebra completamente a construção do loop e, assim, ignora oelse
cláusulaMas, na verdade, meu mapeamento mental é simplesmente que é a versão 'estruturada' do padrão C / C ++:
Então, quando eu o encontro
for...else
ou escrevo, em vez de entendê-lo diretamente , eu traduzo-o mentalmente para o entendimento acima do padrão e depois trabalho quais partes da sintaxe do python são mapeadas para quais partes do padrão.(Coloquei 'estruturado' entre aspas, porque a diferença não é se o código é estruturado ou não estruturado, mas apenas se há palavras-chave e gramática dedicadas à estrutura específica)
fonte
else
? Se você quisesse que odone:
rótuloelse:
fosse proxy ou , acredito que você o tenha exatamente ao contrário.done:
rótulo. Talvez a correspondência geral seja melhor assim: Python possui aelse
construção -on-loop para que você possa expressar esse padrão de fluxo de controle semgoto
.else
evita.Se emparelhar
else
comfor
, pode ser confuso. Não acho que a palavra-chave tenhaelse
sido uma ótima opção para essa sintaxe, mas se você emparelharelse
com aif
que contémbreak
, poderá ver que realmente faz sentido.else
é pouco útil se não houver umaif
declaração anterior e acredito que é por isso que o designer de sintaxe escolheu a palavra-chave.Deixe-me demonstrá-lo na linguagem humana.
fonte
Na minha opinião, a chave é considerar o significado de, em
continue
vez deelse
.As outras palavras-chave que você menciona quebram o loop (saem anormalmente) enquanto
continue
não o fazem, apenas ignoram o restante do bloco de código dentro do loop. O fato de que ele pode preceder a terminação do loop é incidental: na verdade, a terminação é feita da maneira normal pela avaliação da expressão condicional do loop.Então você só precisa se lembrar que a
else
cláusula é executada após o encerramento normal do loop.fonte
fonte