J'ai une compréhension de liste en Python dans laquelle chaque itération peut lever une exception.
Par exemple , si j'ai:
eggs = (1,3,0,3,2)
[1/egg for egg in eggs]
J'obtiendrai une ZeroDivisionError
exception dans le 3ème élément.
Comment puis-je gérer cette exception et continuer l'exécution de la compréhension de la liste?
La seule façon dont je peux penser est d'utiliser une fonction d'assistance:
def spam(egg):
try:
return 1/egg
except ZeroDivisionError:
# handle division by zero error
# leave empty for now
pass
Mais cela me semble un peu compliqué.
Existe-t-il une meilleure façon de faire cela en Python?
Remarque: Ceci est un exemple simple (voir " par exemple " ci-dessus) que j'ai inventé parce que mon exemple réel nécessite un certain contexte. Je ne suis pas intéressé à éviter la division par zéro erreur, mais à gérer les exceptions dans une compréhension de liste.
python
exception
list-comprehension
Nathan Fellman
la source
la source
[1/egg except ZeroDivisionError: None for egg in (1,3,0,3,2)]
. Mais il est toujours en mode brouillon. Mon instinct est que cela ne sera pas accepté. Les expressions Imho peuvent devenir trop compliquées (vérifier plusieurs exceptions, avoir des combinaisons plus complexes (plusieurs opérateurs logiques, des compréhensions complexes, etc.)ndarray
avec les paramètres appropriés dansnp.seterr
. Cela entraînerait1/0 = nan
. Mais je me rends compte que cela ne se généralise pas à d'autres situations où ce besoin se fait sentir.Réponses:
Il n'y a pas d'expression intégrée en Python qui vous permet d'ignorer une exception (ou de renvoyer des valeurs alternatives & c en cas d'exceptions), il est donc impossible, littéralement, de "gérer les exceptions dans une compréhension de liste" car une compréhension de liste est une expression contenant une autre expression, rien de plus (c'est-à-dire aucune instruction, et seules les instructions peuvent intercepter / ignorer / gérer les exceptions).
Les appels de fonction sont des expressions et les corps de fonction peuvent inclure toutes les instructions que vous souhaitez, donc déléguer l'évaluation de la sous-expression sujette aux exceptions à une fonction, comme vous l'avez remarqué, est une solution de contournement possible (d'autres, lorsque cela est possible, sont vérifie les valeurs susceptibles de provoquer des exceptions, comme également suggéré dans d'autres réponses).
Les réponses correctes à la question «comment gérer les exceptions dans une compréhension de liste» expriment toutes une partie de toute cette vérité: 1) littéralement, c'est-à-dire lexicalement DANS la compréhension elle-même, vous ne pouvez pas; 2) en pratique, vous déléguez le travail à une fonction ou vérifiez les valeurs sujettes aux erreurs lorsque cela est possible. Votre affirmation répétée selon laquelle ce n’est pas une réponse n’est donc pas fondée.
la source
[x[1] for x in list except IndexError pass]
. L'interpréteur n'a-t-il pas pu créer une fonction temporaire pour essayerx[1]
?Je me rends compte que cette question est assez ancienne, mais vous pouvez également créer une fonction générale pour faciliter ce genre de chose:
Ensuite, dans votre compréhension:
Vous pouvez bien sûr faire fonctionner la poignée par défaut comme vous le souhaitez (disons que vous préférez retourner «Aucun» par défaut).
J'espère que cela vous aidera, vous ou les futurs téléspectateurs de cette question!
Remarque: dans python 3, je créerais le mot-clé d'argument 'handle' uniquement et le placerais à la fin de la liste d'arguments. Cela rendrait les arguments de passage, etc., beaucoup plus naturels.
la source
args
etkwargs
de gérer. De cette façon, vous pouvez retourner sayegg
au lieu d'un codé en dur0
, ou une exception comme vous le faites.handle
après**kwarg
et a obtenu unSyntaxError
. Voulez-vous déréférencer commekwargs.get('handle',e)
?Vous pouvez utiliser
cela sautera simplement les éléments qui sont nuls.
la source
Non, il n'y a pas de meilleur moyen. Dans de nombreux cas, vous pouvez utiliser l'évitement comme le fait Peter
Votre autre option est de ne pas utiliser les compréhensions
À vous de décider si c'est plus encombrant ou non
la source
Je pense qu'une fonction d'assistance, comme suggéré par celui qui pose la question initiale et Bryan Head aussi, est bonne et pas du tout encombrante. Une seule ligne de code magique qui fait tout le travail n'est tout simplement pas toujours possible, donc une fonction d'assistance est une solution parfaite si l'on veut éviter les
for
boucles. Cependant, je le modifierais pour celui-ci:La sortie sera celle-ci
[(1/1, None), (1/3, None), (None, ZeroDivisionError), (1/3, None), (1/2, None)]
. Avec cette réponse, vous avez le contrôle total pour continuer comme vous le souhaitez.la source
Either
type de certains langages de programmation fonctionnels (comme Scala), où anEither
peut contenir une valeur d'un type ou d'un autre, mais pas les deux. La seule différence est que dans ces langues, il est idiomatique de mettre l'erreur sur le côté gauche et la valeur sur le côté droit. Voici un article avec plus d'informations .Je n'ai vu aucune réponse mentionner cela. Mais cet exemple serait un moyen d'empêcher la levée d'une exception pour les cas d'échec connus.
la source