Outra cláusula no Python while statement

321

Notei que o código a seguir é legal no Python. Minha pergunta é por que? Existe um motivo específico?

n = 5
while n != 0:
    print n
    n -= 1
else:
    print "what the..."
Ivan
fonte
5
@detly: Isso porque a maioria das pessoas evita essa construção. :) Creio que Guido mencionou durante o processo Py3k que, no mínimo, a escolha da palavra elsepara esse uso tinha sido uma ideia extremamente ruim e que eles não fariam mais isso.
Nicholas Knight
5
@ Nicholas Knight - sim, por mais tentador que seja, provavelmente seria algo que só eu entendi à primeira vista. Qualquer outro pobre coitado teria que procurar as especificações do idioma ou voltar no tempo e postar uma pergunta aqui no Sta- heeeeey ...
detly
8
A idéia por trás da escolha de 'else' é que essa construção é supostamente usada em conjunto com um 'if X: break' dentro do loop while. Como a cláusula 'else' é executada se não sairmos do loop, ela forma um tipo de 'else' no 'if'.
Jonathan Hartley
12
Eles devem renomeá-lo after:.
naught101

Respostas:

388

A elsecláusula é executada apenas quando sua whilecondição se torna falsa. Se você breaksair do loop ou se uma exceção for gerada, ela não será executada.

Uma maneira de pensar sobre isso é como uma construção if / else com relação à condição:

if condition:
    handle_true()
else:
    handle_false()

é análogo à construção de loop:

while condition:
    handle_true()
else:
    # condition is false now, handle and go on with the rest of the program
    handle_false()

Um exemplo pode ser ao longo das linhas de:

while value < threshold:
    if not process_acceptable_value(value):
        # something went wrong, exit the loop; don't pass go, don't collect 200
        break
    value = update(value)
else:
    # value >= threshold; pass go, collect 200
    handle_threshold_reached()
ars
fonte
42
"A cláusula else é executada apenas quando sua condição while se torna falsa." A redação aqui implica que o seu estado while passa de um estado true para false e então o outro será executado. No entanto, se o tempo nunca for verdadeiro, a cláusula else ainda será executada.
user597608
pseudocódigo Então, corrija-me se estiver errado, mas isso é exatamente o mesmo que, while {} something exceto que o somethingserá ignorado se você estiver breakno whileloop.
Daniel Kaplan
2
Talvez o pseudocódigo mais preciso seja: while (True) {if (cond) {handle_true (); } else {handle_false (); pausa; }}
VinGarcia 5/16/16
2
"não passar go, não recolhem 200", haha, todo mundo que sabe de onde este é teve uma boa infância
Stefan Octavian
102

A elsecláusula é executada se você sair de um bloco normalmente, atingindo a condição de loop ou caindo na parte inferior de um bloco try. É não executada se você breakou returnfora de um bloco, ou levantar uma exceção. Ele funciona não apenas durante o tempo e para os loops, mas também tenta blocos.

Você normalmente o encontra em lugares onde normalmente você sairia de um loop mais cedo, e correr o final do loop é uma ocasião inesperada / incomum. Por exemplo, se você estiver percorrendo uma lista procurando um valor:

for value in values:
    if value == 5:
        print "Found it!"
        break
else:
    print "Nowhere to be found. :-("
John Kugelman
fonte
1
Na verdade, uma construção bastante útil para tal coisa. Não sei quantas vezes eu coloquei found_it=Falseno início de um loop e, em seguida, faça um check se found_itno final
Cruncher
42

Em resposta Is there a specific reason?, aqui está uma aplicação interessante: rompendo com vários níveis de loop.

Aqui está como funciona: o loop externo tem uma interrupção no final, portanto, seria executado apenas uma vez. No entanto, se o loop interno for concluído (não encontra divisor), ele alcançará a instrução else e a quebra externa nunca será alcançada. Dessa forma, uma quebra no loop interno sairá dos dois loops, em vez de apenas um.

for k in [2, 3, 5, 7, 11, 13, 17, 25]:
    for m in range(2, 10):
        if k == m:
            continue
        print 'trying %s %% %s' % (k, m)
        if k % m == 0:
            print 'found a divisor: %d %% %d; breaking out of loop' % (k, m)
            break
    else:
        continue
    print 'breaking another level of loop'
    break
else:
    print 'no divisor could be found!'

Para ambos whilee forloops, a elseinstrução é executada no final, a menos que tenha breaksido usada.

Na maioria dos casos, existem maneiras melhores de fazer isso (agrupando-o em uma função ou gerando uma exceção), mas isso funciona!

Marca
fonte
1
Não diminuí o voto, mas acho que sei por que alguém o fez. Você não está respondendo à pergunta e está fornecendo 14 linhas de código com apenas 2 linhas de descrição. Se há uma relevância para a pergunta que você não está nos dizendo ...
BlueEel
1
@BlueEel obrigado pelo feedback! Adicionei mais explicações sobre o código e deixei mais claro como isso responde à pergunta (porque responde parte dela).
Mark
Você conseguiu colocar seu código em contexto e, embora não esteja respondendo a todas as perguntas, vejo a relevância agora. Votou sua resposta, já que agora é útil para iniciantes e novatos (como eu no que diz respeito ao python). - Obrigado, eu aprendi uma coisa.
BlueEel
Gosto do aplicativo simples - agora vejo por que alguém pode usá-lo. Embora eu nunca tenha visto necessidade disso.
gabe
O exemplo mostra o uso de for / else, mas a pergunta era especificamente sobre while / else.
Ian Goldby
20

A cláusula else é executada quando a condição while é avaliada como falsa.

A partir da documentação :

A instrução while é usada para execução repetida, desde que uma expressão seja verdadeira:

while_stmt ::=  "while" expression ":" suite
                ["else" ":" suite]

Isso testa repetidamente a expressão e, se for verdade, executa o primeiro conjunto; se a expressão for falsa (que pode ser a primeira vez que é testada), o conjunto da elsecláusula, se presente, é executado e o loop termina.

UMA break instrução executada no primeiro conjunto termina o loop sem executar o elseconjunto da cláusula. Uma continueinstrução executada no primeiro conjunto ignora o restante do conjunto e volta a testar a expressão.

Mark Rushakoff
fonte
15

Minha resposta se concentrará em QUANDO podemos usar while / for-else.

À primeira vista, parece que não há diferenças ao usar

while CONDITION:
    EXPRESSIONS
print 'ELSE'
print 'The next statement'

e

while CONDITION:
    EXPRESSIONS
else:
    print 'ELSE'
print 'The next statement'

Como a print 'ELSE'instrução parece sempre executada nos dois casos (quando owhile loop termina ou não é executado).

Então, só é diferente quando a instrução print 'ELSE'não será executada. É quando existe um breakdentro do bloco de código emwhile

In [17]: i = 0

In [18]: while i < 5:
    print i
    if i == 2:
        break
    i = i +1
else:
    print 'ELSE'
print 'The next statement'
   ....:
0
1
2
The next statement

Se for diferente de:

In [19]: i = 0

In [20]: while i < 5:
    print i
    if i == 2:
        break
    i = i +1
print 'ELSE'
print 'The next statement'
   ....:
0
1
2
ELSE
The next statement

return não está nesta categoria, porque faz o mesmo efeito nos dois casos acima.

O aumento de exceção também não causa diferença, porque quando gera, onde o próximo código será executado está no manipulador de exceções (exceto bloco), o código na elsecláusula ou logo após owhile cláusula não será executado.

HVNSweeting
fonte
4

Eu sei que esta é uma pergunta antiga, mas ...

Como Raymond Hettinger disse, deveria ser chamado em while/no_breakvez de while/else.
Acho fácil entender e se você olhar para este trecho.

n = 5
while n > 0:
    print n
    n -= 1
    if n == 2:
        break
if n == 0:
    print n

Agora, em vez de verificar a condição após o loop while, podemos trocá-la elsee nos livrar dessa verificação.

n = 5
while n > 0:
    print n
    n -= 1
    if n == 2:
        break
else:  # read it as "no_break"
    print n

Eu sempre o leio while/no_breakpara entender o código e essa sintaxe faz muito mais sentido para mim.

Iluvatar
fonte
3

A cláusula else é executada apenas quando a condição while se torna falsa.

aqui estão alguns exemplos:

Exemplo 1: Inicialmente a condição é falsa, portanto , a cláusula else é executada.

i = 99999999

while i < 5:
    print(i)
    i += 1
else:
    print('this')

RESULTADO:

this

Exemplo 2: A condição while i < 5 nunca se tornou falsa porque i == 3quebra o loop; portanto , a cláusula else não foi executada.

i = 0

while i < 5:
    print(i)
    if i == 3:
        break
    i += 1
else:
    print('this')

RESULTADO:

0
1
2
3

Exemplo 3: A condição while i < 5 se tornou falsa quando iwas 5, então a cláusula else foi executada.

i = 0

while i < 5:
    print(i)
    i += 1
else:
    print('this')

RESULTADO:

0
1
2
3
4
this
Saif Ur Rahman
fonte
0

A else:instrução é executada quando e somente quando o loop while não atender mais a sua condição (no seu exemplo, quandon != 0 for falso).

Portanto, a saída seria esta:

5
4
3
2
1
what the...
BoltClock
fonte
Eu sei, mas esse tipo de tempo / else não funciona em Java. Acho isso bastante interessante quando descobri que funciona em Python. Eu estava apenas curioso e queria saber o motivo técnico.
Ivan
6
@ Ivan: Não é tanto que ele não funcione em Java, mas que não exista em Java. Poderia ser feito para funcionar, se alguém quisesse adicioná-lo ao idioma.
Ignacio Vazquez-Abrams
1
Não, enquanto False: .. else .. ainda executa a cláusula else. É mais preciso dizer: senão não é executado se o loop for interrompido.
Leo Ufimtsev
0

Caso contrário, o loop while não quebrou.

Eu meio que gosto de pensar nisso com uma metáfora de 'corredor'.

O "outro" é como cruzar a linha de chegada, não importando se você começou no início ou no final da pista. "else" não é executado apenas se você quebrar em algum lugar.

runner_at = 0 # or 10 makes no difference, if unlucky_sector is not 0-10
unlucky_sector = 6
while runner_at < 10:
    print("Runner at: ", runner_at)
    if runner_at == unlucky_sector:
        print("Runner fell and broke his foot. Will not reach finish.")
        break
    runner_at += 1
else:
    print("Runner has finished the race!") # Not executed if runner broke his foot.

Os principais casos de uso estão usando essa quebra de loops aninhados ou se você deseja executar algumas instruções apenas se o loop não quebrar em algum lugar (pense em quebrar sendo uma situação incomum).

Por exemplo, a seguir está um mecanismo sobre como interromper um loop interno sem usar variáveis ​​ou tentar / capturar:

for i in [1,2,3]:
    for j in ['a', 'unlucky', 'c']:
        print(i, j)
        if j == 'unlucky':
            break
    else: 
        continue  # Only executed if inner loop didn't break.
    break         # This is only reached if inner loop 'breaked' out since continue didn't run. 

print("Finished")
# 1 a
# 1 b
# Finished
Leo Ufimtsev
fonte
-1

O melhor uso da construção 'while: else:' no Python deve ser se nenhum loop for executado em 'while' e a instrução 'else' será executada. A maneira como funciona hoje não faz sentido, porque você pode usar o código abaixo com os mesmos resultados ...

n = 5
while n != 0:
    print n
    n -= 1
print "what the..."
Jean Ferri
fonte
8
Não, a diferença é que o elsebloco não será executado se você estiver saindo do loop usando breakou returnkeyword. No seu exemplo, printserá executado também se o loop terminar no breakcomando.
notsurewhattodo
2
Você descreve como a maioria das pessoas deseja que o recurso funcione, não como ele realmente funciona!
dotancohen
-2

É útil para interação social.

while (Date != "January 1st"):
    time.sleep(1)
else:
    print("Happy new year!")
Guimoute
fonte
2
E qual é exatamente o propósito do elseaqui? O código faz exatamente o mesmo sem ele.
Wovano 19/05/19
Se o seu relógio e calendário breakdurante a contagem regressiva, não usar elseo fará dizer "Feliz Ano Novo!" instantaneamente, o que não faz nenhum sentido.
Guimoute 6/11/19
@ Guimote, o que você quer dizer com "se o seu relógio e calendário break"? Não existe breakno código.
Wovano #