Pourquoi python utilise-t-il 'else' après les boucles for et while?



Answers

Une construction commune est d'exécuter une boucle jusqu'à ce que quelque chose soit trouvé, puis de sortir de la boucle. Le problème est que si je sors de la boucle ou que la boucle se termine, je dois déterminer quel cas s'est produit. Une méthode consiste à créer une variable de drapeau ou de magasin qui me permettra de faire un deuxième test pour voir comment la boucle a été quittée.

Par exemple, supposons que je doive faire une recherche dans une liste et traiter chaque élément jusqu'à ce qu'un élément indicateur soit trouvé, puis arrêter le traitement. Si l'élément d'indicateur est manquant, une exception doit être déclenchée.

En utilisant le Python for ... else construisez vous avez

for i in mylist:
    if i == theflag:
        break
    process(i)
else:
    raise ValueError("List argument missing terminal flag.")

Comparez cela à une méthode qui n'utilise pas ce sucre syntaxique:

flagfound = False
for i in mylist:
    if i == theflag:
        flagfound = True
        break
    process(i)

if not flagfound:
    raise ValueError("List argument missing terminal flag.")

Dans le premier cas, la raise est étroitement liée à la boucle for avec laquelle elle travaille. Dans la seconde, la liaison n'est pas aussi forte et des erreurs peuvent être introduites lors de la maintenance.

Question

Je comprends comment fonctionne cette construction:

for i in range(10):
    print(i)

    if i == 9:
        print("Too big - I'm giving up!")
        break;
else:
    print("Completed successfully")

Mais je ne comprends pas pourquoi d' else est utilisé comme mot clé ici, car il suggère que le code en question ne s'exécute que si le bloc for ne se termine pas, ce qui est le contraire de ce qu'il fait! Peu importe comment je pense à ce sujet, mon cerveau ne peut pas progresser de façon transparente de la déclaration pour l' else bloc. Pour moi, continue ou continuewith plus de sens (et j'essaie de m'entraîner à le lire comme tel).

Je me demande comment les codeurs Python lisent cette construction dans leur tête (ou à haute voix, si vous voulez). Peut-être qu'il me manque quelque chose qui rendrait ces blocs de code plus facilement déchiffrables?




Pour le rendre simple, vous pouvez penser comme ça;

  • S'il rencontre une commande break dans la boucle for , la partie else ne sera pas appelée.
  • Si elle ne rencontre pas de commande break dans la boucle for , la partie else sera appelée.

C'est si simple.




Le mot-clé else peut être déroutant ici, et comme beaucoup de gens l'ont souligné, quelque chose comme nobreak , notbreak est plus approprié.

Afin de comprendre for ... else ... logiquement, comparez-le avec try...except...else , pas if...else... , la plupart des programmeurs python sont familiers avec le code suivant:

try:
    do_something()
except:
    print("Error happened.") # The try block threw an exception
else:
    print("Everything is find.") # The try block does things just find.

De même, pensez à break comme un type spécial d' Exception :

for x in iterable:
    do_something(x)
except break:
    pass # Implied by Python's loop semantics
else:
    print('no break encountered')  # No break statement was encountered

La différence est que python implique except break et vous ne pouvez pas l'écrire, ainsi il devient:

for x in iterable:
    do_something(x)
else:
    print('no break encountered')  # No break statement was encountered

Oui, je sais que cette comparaison peut être difficile et fastidieuse, mais elle clarifie la confusion.




Je l'ai lu quelque chose comme:

Si toujours sur les conditions pour exécuter la boucle, faire des choses, sinon faire autre chose.




Voici un autre cas d'utilisation idiomatique en plus de la recherche. Supposons que vous vouliez attendre qu'une condition soit vraie, par exemple, qu'un port soit ouvert sur un serveur distant, avec un certain délai. Ensuite, vous pouvez utiliser un peu while...else construire comme ça:

import socket
import time

sock = socket.socket()
timeout = time.time() + 15
while time.time() < timeout:
    if sock.connect_ex(('127.0.0.1', 80)) is 0:
        print('Port is open now!')
        break
    print('Still waiting...')
else:
    raise TimeoutError()



Les codes dans else bloc d'instruction else seront exécutés lorsque la boucle for n'est pas rompue.

for x in xrange(1,5):
    if x == 5:
        print 'find 5'
        break
else:
    print 'can not find 5!'
#can not find 5!

A partir des docs

Les instructions de boucle peuvent avoir une clause else; elle est exécutée lorsque la boucle se termine par épuisement de la liste (avec for) ou lorsque la condition devient fausse (avec while), mais pas lorsque la boucle est terminée par une instruction break. Ceci est illustré par la boucle suivante, qui recherche les nombres premiers:

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print(n, 'equals', x, '*', n//x)
...             break
...     else:
...         # loop fell through without finding a factor
...         print(n, 'is a prime number')
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

(Oui, c'est le bon code Regardez de plus près: la clause else appartient à la boucle for, pas à l'instruction if.)

Lorsqu'elle est utilisée avec une boucle, la clause else a plus de points communs avec la clause else d'une instruction try qu'avec une instruction if: une clause else d'instruction try s'exécute lorsqu'aucune exception ne se produit et une clause else d'une boucle s'exécute . Pour plus d'informations sur l'instruction try et les exceptions, voir Gestion des exceptions.

L'instruction continue, également empruntée à C, continue avec la prochaine itération de la boucle:

>>> for num in range(2, 10):
...     if num % 2 == 0:
...         print("Found an even number", num)
...         continue
...     print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9



Parce qu'ils ne voulaient pas introduire un nouveau mot-clé dans la langue. Chacun vole un identifiant et provoque des problèmes de compatibilité ascendante, c'est donc généralement un dernier recours.




Je l'ai lu comme "Quand l' iterable est complètement épuisé, et l'exécution est sur le point de passer à l'instruction suivante après avoir terminé le for , la clause else sera exécutée." Ainsi, lorsque l'itération est rompue par un break , ceci ne sera pas exécuté.




Links