Else-clausule op Python while-statement

Ik heb gemerkt dat de volgende code legaal is in Python. Mijn vraag is waarom? Is er een specifieke reden?

n = 5
while n != 0:
    print n
    n -= 1
else:
    print "what the..."

Antwoord 1, autoriteit 100%

De else-clausule wordt alleen uitgevoerd wanneer uw while-voorwaarde onwaar wordt. Als je breakuit de lus, of als er een uitzondering wordt gemaakt, wordt deze niet uitgevoerd.

Een manier om erover na te denken is als een if/else-constructie met betrekking tot de voorwaarde:

if condition:
    handle_true()
else:
    handle_false()

is analoog aan de looping-constructie:

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

Een voorbeeld kan zijn in de trant van:

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()

Antwoord 2, autoriteit 27%

De else-clausule wordt uitgevoerd als je een blok normaal verlaat, door de lus-voorwaarde te raken of van de onderkant van een try-blok te vallen. Het wordt nietuitgevoerd als je breakof returnuit een blok, of een uitzondering maakt. Het werkt niet alleen voor while en for loops, maar ook voor try-blocks.

Je vindt het meestal op plaatsen waar je normaal gesproken een lus eerder zou verlaten, en het einde van de lus verlaten is een onverwachte/ongewone gelegenheid. Als u bijvoorbeeld door een lijst bladert op zoek naar een waarde:

for value in values:
    if value == 5:
        print "Found it!"
        break
else:
    print "Nowhere to be found. :-("

Antwoord 3, autoriteit 10%

Als antwoord op Is there a specific reason?, hier is een interessante toepassing: het doorbreken van meerdere niveaus van looping.

Dit is hoe het werkt: de buitenste lus heeft een pauze aan het einde, dus het zou maar één keer worden uitgevoerd. Als de binnenste lus echter is voltooid (geen deler vindt), bereikt deze de else-instructie en wordt de buitenste lus nooit bereikt. Op deze manier breekt een breuk in de binnenste lus uit beide lussen, in plaats van slechts één.

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!'

Voor zowel whileals forloops wordt de else-instructie aan het einde uitgevoerd, tenzij breakwas gebruikt.

In de meeste gevallen zijn er betere manieren om dit te doen (verpakken in een functie of een uitzondering maken), maar dit werkt!


Antwoord 4, autoriteit 6%

De else-clausule wordt uitgevoerd wanneer de while-voorwaarde onwaar is.

Uit de documentatie:

Het while-statement wordt gebruikt voor herhaalde uitvoering zolang een expressie waar is:

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

Dit test herhaaldelijk de expressie en, als het waar is, voert het de eerste suite uit; als de uitdrukking onwaar is (wat de eerste keer kan zijn dat deze wordt getest), wordt de suite van de else-clausule, indien aanwezig, uitgevoerd en eindigt de lus.

Een break-instructie die in de eerste suite wordt uitgevoerd, beëindigt de lus zonder de suite van de else-clausule uit te voeren. Een continue-instructie uitgevoerd in de eerste suite slaat de rest van de suite over en gaat terug naar het testen van de expressie.


Antwoord 5, autoriteit 5%

Mijn antwoord gaat over WANNEER we while/for-else kunnen gebruiken.

Op het eerste gezicht lijkt het niet anders te zijn bij het gebruik van

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

en

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

Omdat de print 'ELSE'-instructie altijd lijkt te worden uitgevoerd in beide gevallen (beide wanneer de while-lus is voltooid of niet wordt uitgevoerd).

Dan het is alleen anders als het statement print 'ELSE'niet wordt uitgevoerd.
Het is wanneer er een breakin het codeblok is onder while

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

Indien verschillend van:

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

returnvalt niet in deze categorie, omdat het hetzelfde effect heeft voor twee bovenstaande gevallen.

uitzonderingverhoging veroorzaakt ook geen verschil, omdat wanneer de verhoging wordt uitgevoerd, de volgende code wordt uitgevoerd in de uitzonderingshandler (behalve blok), de code in de else-clausule of direct na de while-clausule wordt niet uitgevoerd.


Antwoord 6, autoriteit 5%

De else-clausule wordt alleen uitgevoerd wanneer de while-voorwaardeonwaar wordt.

Hier zijn enkele voorbeelden:

Voorbeeld 1:Aanvankelijk is de voorwaarde onwaar, dus else-clausewordt uitgevoerd.

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

UITGANG:

this

Voorbeeld 2:De terwijl-voorwaardei < 5is nooit onwaar geworden omdat i == 3de lus verbreekt, dus else-clausewerd niet uitgevoerd.

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

UITGANG:

0
1
2
3

Voorbeeld 3:De terwijl-voorwaardei < 5werd onwaar toen i5was, dus else-clausewerd uitgevoerd.

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

UITGANG:

0
1
2
3
4
this

Antwoord 7, autoriteit 2%

Ik weet dat dit een oude vraag is, maar…

Zoals Raymond Hettinger zei, zou het while/no_breakmoeten heten in plaats van while/else.
Ik vind het gemakkelijk te begrijpen als je naar dit fragment kijkt.

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

In plaats van de voorwaarde na de while-lus te controleren, kunnen we deze verwisselen met elseen die controle verwijderen.

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

Ik lees het altijd als while/no_breakom de code te begrijpen en die syntaxis is voor mij veel logischer.


Antwoord 8

De else:-instructie wordt uitgevoerd wanneer en alleen wanneer de while-lus niet langer aan de voorwaarde voldoet (in uw voorbeeld, wanneer n != 0onwaar is).

Dus de uitvoer zou dit zijn:

5
4
3
2
1
what the...

Antwoord 9

Anders wordt uitgevoerd als de while-lus niet is verbroken.

Ik vind het leuk om eraan te denken met een ‘runner’-metafoor.

Het “anders” is als het overschrijden van de finishlijn, irrelevant of u aan het begin of het einde van de baan begon. “anders” is alleen niet uitgevoerd als u ergens tussendoor breekt.

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.

Hoofdgebruikszaken gebruikt dit uitbreken van geneste lussen of als u alleen een aantal uitspraken wilt uitvoeren als de lus niet ergens brak (denk aan het breken van een ongebruikelijke situatie).

Bijvoorbeeld, het volgende is een mechanisme over het uitbreken van een binnenlus zonder variabelen te gebruiken of / proberen / vangen:

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

Antwoord 10

Stel dat u een element x in een enkele gelinkte lijst

kunt zoeken

   def search(self, x):
        position = 1
        p =self.start
        while p is not None:
            if p.info == x:
                print(x, " is at position ", position)
                return True
            position += 1
            p = p.link
        else:
            print(x, "not found in list") 
            return False

Dus als de voorwaarden niet werken, worden andere uitgevoerd, hoop dat het helpt!


Antwoord 11

Het beste gebruik van de constructie ‘while: else:’ in Python zou moeten zijn dat als er geen lus wordt uitgevoerd in ‘while’, dan wordt de instructie ‘else’ uitgevoerd. De manier waarop het vandaag werkt, is niet logisch, omdat je de onderstaande code kunt gebruiken met dezelfde resultaten…

n = 5
while n != 0:
    print n
    n -= 1
print "what the..."

Antwoord 12

Voor zover ik weet, is de belangrijkste reden voor het toevoegen van else aan loops in welke taal dan ook, in gevallen waarin de iterator niet in uw controle is. Stel je voor dat de iterator op een server staat en je geeft hem gewoon een signaal om de volgende 100 gegevensrecords op te halen. Je wilt dat de lus doorgaat zolang de lengte van de ontvangen gegevens 100 is. Als het minder is, moet je hem nog een keer herhalen en dan beëindigen. Er zijn veel andere situaties waarin je geen controle hebt over de laatste iteratie. De optie om in deze gevallen een else toe te voegen, maakt alles veel gemakkelijker.

Other episodes