43 votes

Pourquoi la clause `continue` n'est pas autorisée dans une clause `finally` en Python ?

Le code suivant soulève une erreur de syntaxe :

>>> for i in range(10):
...     print i
...     try:
...        pass
...     finally:
...        continue
...     print i
...
  File "<stdin>", line 6
SyntaxError: 'continue' not supported inside 'finally' clause

Pourquoi n'y a-t-il pas un continue autorisée à l'intérieur d'un finally clause ?

P.S. Cet autre code, par contre, n'a aucun problème :

>>> for i in range(10):
...     print i
...     try:
...        pass
...     finally:
...        break
...
0

Si cela a une importance, j'utilise Python 2.6.6.

26voto

Raymond Hettinger Points 50330

L'utilisation de continuer dans une clause finale est interdite car son interprétation aurait été problématique. Que feriez-vous si la clause finale était exécutée à cause d'une exception ?

for i in range(10):
    print i
    try:
       raise RuntimeError
    finally:
       continue        # if the loop continues, what would happen to the exception?
    print i

Il est possible pour nous de prendre une décision sur ce que ce code devrait faire, peut-être en avalant l'exception ; mais une bonne conception du langage suggère autre chose. Si le code embrouille les lecteurs ou s'il existe une manière plus claire d'exprimer la logique voulue (peut-être avec des try: ... except Exception: pass; continue ), il y a un certain avantage à laisser cet élément en tant que Erreur de syntaxe .

Il est intéressant de noter que vous pouvez mettre un retourner à l'intérieur d'une clause finale et il avalera toutes les exceptions y compris KeyboardInterrupt , SystemExit y Erreur de mémoire . Ce n'est probablement pas une bonne idée non plus ;-)

6voto

wim Points 35274

Une instruction continue était illégale dans la clause finally en raison d'un problème d'implémentation. Dans Python 3.8, cette restriction a été levée.

Le bug était issue32489 - Autoriser "continue" dans la clause "finally .

La demande de retrait pour la correction : https://github.com/python/cpython/pull/5822

6voto

Michael Hoffman Points 8557

La référence du langage Python interdit l'utilisation de continue dans un finally clause. Je ne sais pas vraiment pourquoi. Peut-être parce que continue au sein de la try garantit que la clause finally est exécutée, et de décider ce que continue devrait faire dans le cadre de la finally est quelque peu ambiguë.

Editer : Le commentaire de @Mike Christensen à la question indique un fil de discussion où l'ambiguïté de cette construction est discutée par les développeurs du noyau Python. De plus, en plus de neuf ans d'utilisation de Python, je n'ai jamais voulu faire cela, donc c'est probablement une situation relativement rare sur laquelle les développeurs n'ont pas envie de passer beaucoup de temps.

2voto

La possibilité d'obtenir une exception levée et ensuite simplement avalée parce que vous utilisez une continue est un argument fort, mais l'exception est également avalée lorsque vous utilisez un break ou return à la place.

Par exemple, ceci fonctionne et l'exception est avalée :

for i in range(10):
    print i
    try:
        raise Exception
    finally:
        break
    print i       # not gonna happen

Cela fonctionne à nouveau sans erreur (dans une fonction) et l'exception est également avalée :

for i in range(10):
    print i
    try:
        raise Exception
    finally:
        return
    print i       # not gonna happen

Alors pourquoi break y return être autorisé dans un finally avec ou sans les éventuelles erreurs soulevées, mais continue pas ?

Vous pouvez également considérer la combinaison des facteurs suivants dans la question :

  • finally est toujours exécuté ;
  • continue "abandonne" l'itération en cours.

Cela signifie qu'à l'intérieur de chaque boucle, en raison de l'utilisation de la fonction finally toujours en cours d'exécution, vous aurez toujours un continue sorcière essentiellement dit "annuler l'itération actuelle", "annuler l'itération actuelle", "annuler l'itération actuelle" ... ce qui n'a pas vraiment de sens. Mais cela n'a pas de sens non plus d'utiliser break y return . L'itération en cours est également interrompue à la seule différence que que vous vous retrouvez maintenant avec une seule itération.

Donc la question "Pourquoi continue non autorisé dans un finally ?" peut également se poser la question suivante : "Pourquoi le break y return autorisé ?".

Peut-être parce que ça avait du sens de ne pas le faire à ce moment-là ? C'était la décision des développeurs et maintenant c'est comme ça ? Bien sûr, cela pourrait aussi être la paresse de l'implémenteur, mais qui sait, peut-être avaient-ils quelque chose en tête et peut-être que, dans une autre version de Python, il serait plus logique d'avoir une autre façon de procéder. plus logique de le faire d'une autre manière ?

L'idée est que les exemples ici sont juste extrêmes . On n'écrit pas du code comme ça, n'est-ce pas ? Il y a sûrement des logique dans le finally bloc pour dire quand break/return/continue ou quoi que ce soit d'autre, et ne pas se contenter d'être aussi direct que ça. En tant que tel, IMHO continue à l'intérieur d'un finally devrait être autorisé parce que j'apprécierais d'écrire un code propre avec l'utilisation de continue sur finally si c'est ce dont j'ai besoin, au lieu de recourir à un code de contournement pour cette limitation (c'est-à-dire dans la philosophie de Python "Nous sommes tous des adultes consentants ici").

2voto

Josh Imhoff Points 1312

Je pense que la raison de ce phénomène est en fait assez simple. L'instruction continue après le mot-clé finally est exécutée à chaque fois. C'est la nature même de l'instruction finally. Que votre code lève ou non une exception n'est pas pertinent. L'instruction finally sera exécutée.

Par conséquent, votre code...

for i in range(10):
   print i
   try:
       pass
   finally:
       continue
   print i # this (and anything else below the continue) won't ever be executed!

est équivalent à ce code...

for i in range(10:
    print i
    try:
        pass
    finally:
        pass

qui est plus propre et plus rapide. Python ne permet pas de continuer dans un bloc finally car tout le code après le continue ne sera jamais exécuté. (Sparse est mieux que dense).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X