Eu entendo como essa construção funciona:
for i in range(10):
print(i)
if i == 9:
print("Too big - I'm giving up!")
break;
else:
print("Completed successfully")
Mas não entendo por que else
é usada como palavra-chave aqui, pois sugere que o código em questão só é executado se o for
bloco não for concluído, o que é o oposto do que faz! Não importa como eu pense sobre isso, meu cérebro não pode progredir perfeitamente da for
declaração para o else
bloco. Para mim, continue
ou continuewith
faria mais sentido (e estou tentando me treinar para lê-lo como tal).
Eu estou querendo saber como os codificadores Python lêem essa construção em suas cabeças (ou em voz alta, se você quiser). Talvez esteja faltando algo que tornaria esses blocos de código mais facilmente decifráveis?
python
if-statement
for-loop
for-else
Kent Boogaart
fonte
fonte
break
é muito usada em "Eu encontrei ele" loops, você pode traduzi-lo para "se não for encontrado" , que não está longe do queelse
lêfor ... else foo()
e apenas colocarfoo()
depois do loop for?" E a resposta é que eles se comportam de maneira diferente apenas se o loop contiver umbreak
(como descrito em detalhes abaixo).Respostas:
É uma construção estranha mesmo para codificadores Python experientes. Quando usado em conjunto com for-loops, significa basicamente "encontre algum item no iterável, caso contrário, se nenhum foi encontrado, faça ...". Como em:
Mas sempre que você vê essa construção, uma alternativa melhor é encapsular a pesquisa em uma função:
Ou use uma compreensão da lista:
Não é semanticamente equivalente às outras duas versões, mas funciona bem o suficiente no código crítico sem desempenho, onde não importa se você interage ou não a lista inteira. Outros podem discordar, mas eu pessoalmente evitaria usar os blocos for-else ou while-else no código de produção.
Veja também [Python-ideas] Resumo dos tópicos for ... else
fonte
for
exemplos de loop, e quiser usar uma expressão de gerador / compreensão de lista, desejenext((o for o in objects if o.key == search_key), None)
ou envolva-o emtry
/except
e não use nenhum valor padrão em vez deif
/else
.for/else
construção.else
fui emparelhado com umfor
e não fazia ideia de que era legal.break
instrução seja explicitamente executada como neste exemplo. Dos documentos acima: "Aelse
cláusula tem outro problema percebido: se não houverbreak
no loop, aelse
cláusula é funcionalmente redundante.". por exemplofor x in [1, 2, 3]:\n print x\n else:\n print 'this executes due to no break'
Uma construção comum é executar um loop até que algo seja encontrado e depois sair do loop. O problema é que, se eu sair do loop ou o loop terminar, preciso determinar qual caso aconteceu. Um método é criar um sinalizador ou armazenar uma variável que me permita fazer um segundo teste para ver como o loop foi encerrado.
Por exemplo, suponha que eu precise pesquisar em uma lista e processar cada item até que um item de sinalizador seja encontrado e pare o processamento. Se o item do sinalizador estiver ausente, será necessária uma exceção.
Usando a construção Python
for
...else
você temCompare isso com um método que não usa este açúcar sintático:
No primeiro caso, ele
raise
está vinculado firmemente ao loop for com o qual trabalha. No segundo, a ligação não é tão forte e erros podem ser introduzidos durante a manutenção.fonte
Python: the good parts
livro.process(i)
acontece para todos os itensmylist
estritamente antestheflag
e não paratheflag
si mesmo? É o que foi planejado?process
será executado em cada umi
que existe na lista antes detheflag
ser atingido, não será executado nos elementos da lista depoistheflag
e não será executadotheflag
.Há uma excelente apresentação de Raymond Hettinger, intitulada Transforming Code into Beautiful, Python Idiomatic , na qual ele aborda brevemente a história da
for ... else
construção. A seção relevante é "Distinguindo vários pontos de saída em loops", começando às 15:50 e continuando por cerca de três minutos. Aqui estão os pontos altos:for ... else
construção foi criada por Donald Knuth como um substituto para certosGOTO
casos de uso;else
palavra - chave fazia sentido porque "era o que Knuth usava, e as pessoas sabiam, na época, que todas as [for
declarações] haviam incorporado umif
eGOTO
por baixo, e esperavam oelse
;"Portanto, se a pergunta for: "Por que eles não alteram essa palavra-chave?" então o Cat Plus Plus provavelmente deu a resposta mais precisa - nesse momento, seria muito destrutivo para o código existente ser prático. Mas se a pergunta que você realmente está perguntando é por que
else
foi reutilizada em primeiro lugar, bem, aparentemente parecia uma boa ideia na época.Pessoalmente, gosto do compromisso de comentar
# no break
em linha onde quer queelse
possa ser confundido, de relance, como pertencendo ao loop. É razoavelmente claro e conciso. Esta opção recebe uma breve menção no resumo que Bjorn vinculou no final de sua resposta:* Citação de bônus dessa parte do vídeo: "Assim como se chamássemos lambda makefunction, ninguém perguntaria: 'O que o lambda faz?'"
fonte
Porque eles não queriam introduzir uma nova palavra-chave no idioma. Cada um rouba um identificador e causa problemas de compatibilidade com versões anteriores, por isso geralmente é o último recurso.
fonte
finally
teria sido uma escolha melhor nesse caso. A palavra-chave finalmente ainda não estava presente no momento em que essa construção foi introduzida?finally
não é muito melhor, porque implica que o bloco sempre será executado após o loop, e não é (porque seria redundante apenas colocar o código para executar após o loop).finally
porque a cláusula else é executada também quandocontinue
é usada no loop for - isso é possível muitas vezes e não apenas no final.else
execução cláusula não é afetado porcontinue
( docs e código de teste )else
é executado apenas quandocontinue
foi o da última iteração.Para simplificar, você pode pensar assim;
break
comando nofor
loop, aelse
parte não será chamada.break
comando nofor
loop, aelse
parte será chamada.Em outras palavras, se a iteração for loop não for "interrompida"
break
, aelse
parte será chamada.fonte
else
bloco também não será executado se o corpo do loop gerar uma exceção.A maneira mais fácil de encontrar o que o for / else fez e, mais importante, quando usá-lo, foi me concentrar em onde a declaração de interrupção salta. A construção For / else é um único bloco. O intervalo salta para fora do bloco e, assim, salta 'sobre' a cláusula else. Se o conteúdo da cláusula else simplesmente seguisse a cláusula for, ela nunca seria ignorada e, portanto, a lógica equivalente teria que ser fornecida colocando-a em um if. Isso já foi dito antes, mas não exatamente nessas palavras, por isso pode ajudar outra pessoa. Tente executar o seguinte fragmento de código. Sou totalmente a favor do comentário "sem interrupção" para maior clareza.
fonte
for:
/else:
, ele realmente não fornece uma justificativa para a palavra-chave serelse
. Dada a estrutura dada aqui,then:
parece que seria muito mais natural. (Não são razões paraelse
ser escolhido, dadas em outras respostas - eles apenas não está fornecidas aqui.)Eu acho que a documentação tem uma ótima explicação de mais , continue
Fonte: Python 2 docs: Tutorial sobre controle de fluxo
fonte
Eu li algo como:
Se ainda sobre as condições para executar o loop, fazer coisas, o mais fazer outra coisa.
fonte
for:
/else:
faz parecer que oelse:
sempre será executado após o loop, o que não é o caso.Como a parte técnica foi praticamente respondida, meu comentário está relacionado à confusão que produz essa palavra-chave reciclada .
Sendo o Python uma linguagem de programação muito eloqüente , o uso indevido de uma palavra-chave é mais notório. A
else
palavra-chave descreve perfeitamente parte do fluxo de uma árvore de decisão, "se você não pode fazer isso, (mais) faz isso". Está implícito em nossa própria língua.Em vez disso, o uso dessa palavra-chave com instruções
while
efor
cria confusão. O motivo, nossa carreira como programadores nos ensinou que aelse
declaração reside em uma árvore de decisão; seu escopo lógico , um invólucro que retorna condicionalmente um caminho a seguir. Enquanto isso, as instruções de loop têm um objetivo explícito figurativo de alcançar algo. O objetivo é alcançado após iterações contínuas de um processo.if / else
indicar um caminho a seguir . Os loops seguem um caminho até que o "objetivo" seja concluído .A questão é que
else
é uma palavra que define claramente a última opção em uma condição. A semântica da palavra é compartilhada por Python e Human Language. Mas a palavra else em Human Language nunca é usada para indicar as ações que alguém ou alguma coisa executará após a conclusão de algo. Ele será usado se, no processo de conclusão, surgir um problema (mais como uma declaração de quebra ).No final, a palavra-chave permanecerá em Python. É claro que foi um erro, mais claro quando todo programador tenta criar uma história para entender seu uso como um dispositivo mnemônico. Eu adoraria se eles tivessem escolhido a palavra-chave
then
. Acredito que essa palavra-chave se encaixa perfeitamente nesse fluxo iterativo, o retorno após o loop.Assemelha-se à situação que uma criança tem depois de seguir todos os passos na montagem de um brinquedo: E ENTÃO o que papai?
fonte
Eu li como "Quando o
iterable
arquivo estiver completamente esgotado, e a execução estiver prestes a prosseguir para a próxima instrução depois de terminar ofor
, a cláusula else será executada". Assim, quando a iteração é interrompidabreak
, isso não será executado.fonte
Eu concordo, é mais como um 'elif not (condição (s) que aumenta o intervalo]'.
Sei que esse é um tópico antigo, mas estou analisando a mesma pergunta agora e não tenho certeza de que alguém tenha capturado a resposta para essa pergunta da maneira que eu a entendo.
Para mim, existem três maneiras de "ler" as instruções
else
inFor... else
ouWhile... else
, todas equivalentes, são: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)
(presumivelmente existe essa condição ou você não teria um loop)Portanto, essencialmente, o "else" em um loop é realmente um "elif ..." onde '...' é (1) sem interrupção, o que equivale a (2) NOT [condição (s) que aumenta a interrupção].
Eu acho que a chave é que isso
else
é inútil sem o 'intervalo', então afor...else
inclui:Portanto, os elementos essenciais de um
for...else
loop são os seguintes, e você os leria em inglês mais claro como:Como os outros pôsteres disseram, geralmente ocorre uma interrupção quando você é capaz de localizar o que seu loop está procurando,
else:
tornando - se "o que fazer se o item de destino não estiver localizado".Exemplo
Você também pode usar manipulação de exceção, quebras e loops todos juntos.
Resultado
Exemplo
Exemplo simples com uma quebra sendo atingida.
Resultado
Exemplo
Exemplo simples em que não há interrupção, nenhuma condição que gera uma interrupção e nenhum erro é encontrado.
Resultado
fonte
A
else
palavra-chave pode ser confusa aqui e, como muitas pessoas apontaram, algo comonobreak
,notbreak
é mais apropriado.Para entender
for ... else ...
logicamente, compare-o comtry...except...else
, e nãoif...else...
, a maioria dos programadores python está familiarizada com o seguinte código:Da mesma forma, pense
break
como um tipo especial deException
:A diferença está
python
implícitaexcept break
e você não pode escrevê-la, então ela se torna:Sim, eu sei que essa comparação pode ser difícil e cansativa, mas esclarece a confusão.
fonte
Os códigos no
else
bloco de instruções serão executados quando ofor
loop não for quebrado.Dos documentos: quebrar e continuar instruções e outras cláusulas em loops
fonte
Aqui está uma maneira de pensar sobre isso que eu não vi mais ninguém mencionar acima:
Primeiro, lembre-se de que os for-loops são basicamente apenas açúcar sintático em torno dos while-loops. Por exemplo, o loop
pode ser reescrito (aproximadamente) como
Segundo, lembre-se de que os while-loops são basicamente apenas repetidos if-blocks! Você sempre pode ler um loop while como "se essa condição for verdadeira, execute o corpo e volte e verifique novamente".
Portanto, while / else faz todo sentido: é exatamente a mesma estrutura que if / else, com a funcionalidade adicional de loop até que a condição se torne falsa, em vez de apenas verificar a condição uma vez.
E então for / else também faz todo o sentido: como todos os loops for são apenas açúcar sintático em cima dos loops while, você só precisa descobrir qual é a condicionalidade implícita subjacente do loop while, e então o resto corresponde a quando condição torna-se falsa.
fonte
Ótimas respostas são:
Minha observação aqui vem do que Donald Knuth disse uma vez (desculpe, não consigo encontrar referência) de que existe uma construção em que while-else é indistinguível de if-else, a saber (em Python):
tem o mesmo fluxo (excluindo diferenças de baixo nível) que:
O ponto é que o if-else pode ser considerado como açúcar sintático por enquanto, o que está implícito
break
no final de seuif
bloco. A implicação oposta, à qual essewhile
loop é extensãoif
, é mais comum (é apenas uma verificação condicional repetida / em loop), porqueif
geralmente é ensinada anteswhile
. No entanto, isso não é verdade, porque isso significaria umelse
bloqueio enquanto outro seria executado sempre que a condição for falsa.Para facilitar sua compreensão, pense dessa maneira:
Outra nota:
fonte
Você poderia pensar nisso como,
else
no resto das coisas, ou nas outras coisas, que não foi feito no circuito.fonte
"else" aqui é loucamente simples, apenas significa
1, "se
for clause
for concluído"É empolgante escrever declarações longas como "para a cláusula for concluída", para que elas introduzam "else".
else
aqui está um se em sua natureza.2, no entanto, que tal
for clause is not run at all
Portanto, é completamente declaração é combinação lógica:
ou coloque desta maneira:
ou desta maneira:
fonte
Aqui está outro caso de uso idiomático além da pesquisa. Digamos que você queira esperar que uma condição seja verdadeira, por exemplo, uma porta a ser aberta em um servidor remoto, juntamente com algum tempo limite. Então você pode utilizar uma
while...else
construção como esta:fonte
Eu só estava tentando entender isso de novo. Eu achei que o seguinte ajuda!
• Pense no
else
como sendo emparelhado com oif
interior do loop (em vez de com ofor
) - se a condição for atendida, quebre o loop, caso contrário, faça isso - exceto que seja umelse
emparelhado com váriosif
s!• Se nenhum
if
s foi satisfeito, faça oelse
.• Os múltiplos
if
s também podem ser considerados comoif
-elif
s!fonte
Considero a estrutura como (if) A else B, e for (if) -seo é um if-else especial , aproximadamente . Pode ajudar a entender mais .
A e B são executados no máximo uma vez, o que é a mesma estrutura if-else.
for (if) pode ser considerado como um if especial, que executa um loop para tentar atender à condição if. Quando a condição if for atendida, A e interrompa ; Else , B.
fonte
O Python usa outros loops for e while para que, se nada se aplica ao loop, algo mais aconteça. Por exemplo:
A saída seria 'Hi' repetidamente (se eu estiver correto).
fonte