2009-08-05 6 views
4

Ce qui suit fonctionne bien, ce qu'il ne donne pas d'erreur:classes imbriquées dans des fonctions et des attributs de recherche

def foo(arg): 
    class Nested(object): 
     x = arg 

foo('hello') 

Mais ce qui suit renvoie une exception:

def foo(arg): 
    class Nested(object): 
     arg = arg # note that names are the same 

foo('hello') 

Traceback:

Traceback (most recent call last): 
    File "test.py", line 6, in <module> 
    foo('hello') 
    File "test.py", line 3, in foo 
    class Nested(object): 
    File "test.py", line 4, in Nested 
    arg = arg 
NameError: name 'arg' is not defined 

Je ne peux pas comprendre la raison d'un tel comportement. Quelqu'un pourrait-il expliquer?

Répondre

5

Les ombres propriété arg l'argument de la fonction arg (de portée intérieure)

def foo(arg): 
    class Nested(object): 
     arg = arg # you try to read the `arg` property which isn't initialized 


Vous obtenez la même erreur si vous tapez i = i dans la fenêtre de l'interpréteur sans avoir initialisé la variable i.

+0

+1: Cela fonctionne aussi si vous aviez "arg = 12", mais Dans ce cas, la variable arg transmise et la variable arg appartenant à la classe Nested sont 2 variables séparées – Steg

+0

Cela n'explique pas pourquoi x = arg fonctionne alors, il devrait échouer pour la même raison, mais ce n'est pas le cas. La vraie raison est, comme l'a souligné Daniel, que Python assume son local parce qu'il lui est assigné. –

+0

Essayez d'insérer 'x = arg' juste avant 'arg = arg' et vous obtiendrez la même erreur sur cette nouvelle ligne. A ce moment, l'argument de foo n'est pas encore occulté. N'est-ce pas? – nkrkv

3

Si vous tentez d'affecter une variable à une fonction, Python suppose que cette variable est locale à cette fonction. Donc, en essayant d'assigner arg à la valeur de lui-même, vous le déclarez implicitement comme une variable locale.

3

Il est dû aux règles de portée de Python:

def foo(arg): # (1) 
    class Nested(object): 
     arg = arg # (2) 

(2) définit un nouveau nom « arg » dans la classe espace de noms, qui Opaques la valeur de l'autre « arg » dans l'espace extérieur (1).

Cependant, (2) est inutile et ce qui suit est tout à fait valable:

def foo(arg): 
    class Nested(object): 
     def message(self): 
      print arg 
    return Nested() 

nested = foo('hello') 
nested.message() 

(impressions) hello

+0

Mais dans (2) arg dans l'espace de noms de classe n'est pas encore défini au moment où arg de (1) est utilisé. Essayez d'insérer 'x = arg' juste avant (2) et vous obtiendrez la même erreur sur cette nouvelle ligne. À ce moment-là, arg n'est définitivement pas encore défini au niveau de la classe. Donc, OMI le problème est ailleurs. – nkrkv

+1

Le problème persiste à cause des règles de portée de python (regardez ici: http://docs.python.org/tutorial/classes.html#python-scopes-and-name-spaces). 'arg' étant sur le côté gauche d'une assignation, le nom du bloc entier est ombré, même pour les lignes précédentes. –