2010-11-10 9 views
1

J'ai une bonne compréhension de la clause try-except de python, mais je rencontre des problèmes lorsque j'essaie de la mettre dans une fonction.Python Try-Except à l'intérieur de la fonction

>>> def tryAppend(child, parent): 
...  try: 
...    parent.append(child) 
...  except NameError: 
...    print "WRONG NAME" 
>>> var1 = [] 
>>> var2 = 'test2' 
>>> tryAppend(var2, var1) #works, no error 
>>> tryAppend(foo, var1) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'foo' is not defined 

c'est presque comme si python ne voyait pas l'instruction try:. Toute aide est appréciée.

+0

var2 est un espace de noms pour la chaîne « test2 ».Si vous voulez entrer une chaîne 'foo', alors vous devez l'encapsuler dans '' ou "", sinon, si foo n'est pas défini ailleurs dans le programme comme une fonction ou une classe ou autre, cela ne fonctionne pas. Essentiellement, vous essayez d'utiliser un espace de noms avant de le déclarer. – momo

Répondre

5

Cela n'a rien à voir avec votre gestionnaire d'exceptions. L'erreur que vous voyez est parce que "foo" n'est défini nulle part.

4

L'erreur de nom se produit avant même qu'il ne soit dans tryAppend. Il évalue la valeur de foo en essayant de le passer à la fonction. Cela fonctionne:

def tryAppend(child, parent): 
    parent.append(child) 

var1 = [] 
try: 
    tryAppend(foo, var1) 
except NameError: 
    print 'WRONG NAME' 
+0

Merci Jonathan. Je n'étais pas que c'était le processus dans lequel les variables ont été évaluées. Donc, cela rend impossible de passer une variable indéfinie dans une fonction, non? Essayez simplement de rendre le code aussi propre que possible .... – garen

+0

Si vous voulez passer une variable "indéfinie" dans une fonction, vous pouvez essayer de passer les locals() à la place. –

+0

@garen: N'écrivez pas du code qui déclenche NameErrors. Assurez-vous qu'ils reçoivent toujours une certaine valeur (sensible!) Dans tous les chemins de code **, ou mourez tôt et envoyez un message d'erreur significatif lorsque vous vous retrouvez avec un état qui ne vous permet pas de continuer (de façon significative). – delnan

2

Le NameError est levée lorsque le nom « foo » est évaluée, ce qui est avant d'entrer dans la fonction. Par conséquent, l'essai/sauf dans la fonction n'est pas pertinent.

0

foo exception se produit même avant d'entrer la fonction tryAppend(), c'est-à-dire en dehors de la fonction.

8

J'ai une assez bonne compréhension de ce python try-except clause

Non Eh bien, peut-être que vous avez, mais vous manquent sévèrement dans d'autres domaines beaucoup plus importants. Soit vous vous attendez à ce que la portée de try (jeu de mots non intentionnel) se développe par magie, soit vous ne comprenez pas dans quel code d'ordre est évalué ... Je vais supposer que ce dernier. tryAppend(foo, var1) est évaluée (à peu près) dans cet ordre:

  1. chercher l'objet tryAppend références
  2. Fetch l'objet foo références
  3. Fetch l'objet var1 références
  4. Appeler la première à la seconde et troisième comme arguments (= faire ce que fait la fonction tryAppend, sans l'essayer-sauf)

L'erreur ou se produit au n ° 2, bien avant que la fonction et le bloc try ne soient entrés. En fait, le bloc try ne peut pas lancer une erreur NameError, car les seuls noms utilisés sont parent et child, les deux étant des arguments et donc toujours disponibles (si .append n'existe pas, c'est un AttributeError).

Vous vous demandez pourquoi

raise Exception("Catch me if you can") 
try: 
    pass # do nothing 
except: 
    print "caught it" 

n'imprime pas "attrapé".

+0

Je suis une horrible personne nitpicky et je veux dire que le bloc try pourrait déclencher une erreur de nom, dire si 'parent.append' en a jeté un. Mais c'est idiot =). – katrielalex

+0

@katriealex: Vous avez raison ... dans le contexte de nitpicking :) – delnan

0

Pour quelqu'un qui cherche à utiliser essayer, sauf la construction à l'intérieur de la fonction. Je ne suis pas sûr que ce soit un bon style de programmation, mais cela fonctionne.

Vous pouvez placer des arguments de chaîne dans la fonction. Il sera évalué correctement et vous pouvez alors utiliser exec à l'intérieur de la fonction:

def tryAppend(child, parent): 
    try: 
     script = parent + '.append(' + child + ')' 
     exec script 
     return parent 
    except NameError: 
     print "WRONG NAME" 
var1 = [] 
var2 = 'test2' 
tryAppend('var2', 'var1') 
tryAppend('foo', 'var1') 
Questions connexes