2009-09-18 7 views

Répondre

6

Utilisons un exemple plus simple pour le même problème:

a = 'something' 
def boo(): 
    a = a 
boo() 

Cela échoue parce que les affectations en python, sans une déclaration global ou nonlocal accompagnant, signifie que le nom attribué est local à la portée actuelle. Cela se produit non seulement dans les fonctions, mais aussi dans les définitions de classe. Cela signifie que vous ne pouvez pas utiliser le même nom pour une variable globale et locale et les utiliser tous les deux. Vous pouvez utiliser la solution de la réponse d'Aaron Digulia, ou utiliser un autre nom:

def make_class(_a): 
    class A(object): 
     a = _a 
    return A 
2

Les deux semblent fonctionner correctement (en Python 2.5, au moins):

>>> def make_class(a): 
...  class A(object): 
...    _a = a 
...  return A 
... 
>>> make_class(10)._a 
10 
>>> def make_class(b): 
...  class B(object): 
...    def get_b(self): 
...      return b 
...  return B 
... 
>>> make_class(10)().get_b() 
10 
+0

Je tentais de faire a = dans la classe, comme dans un argument de fonction par défaut, et cela ne fonctionne pas. – joeforker

9

fonctionne très bien:

>>> def make_class(a): 
    class A(object): 
     _a=a 
    return A 

>>> make_class('df') 
<class '__main__.A'> 
>>> make_class('df')._a 
'df' 

BTW, function est pas un mot-clé réservé en Python.

+1

mon mauvais. Je connais Python, honnête! – joeforker

+3

@joeforker, donc acceptez la réponse de SilentGhost déjà! -) –

2

Essayez

def make_class(a): 
    class A(object): pass 
    A.a=a 
    return A 

L'erreur que vous obtenez (NameError: name 'a' is not defined) est parce que le nom a dans l'ombre classe le paramètre a de la fonction; par conséquent, il n'y a pas a défini lorsque vous essayez "a = a" dans votre code. En d'autres termes, le côté droit a est pas le a du def; Au lieu de ça, Python le cherche dans la classe A puisque a était déjà mentionné sur le côté gauche de la tâche.

Cela devient plus propre avec des fonctions:

x = 1 
def a(x): 
    print 'a:',x 
    x = 3 
    def b(): 
     print 'b:',x 
    b() 
a(2) 
def c(): 
    x = x 

De toute évidence, la première impression doit imprimer 2, pas 1, de sorte que le paramètre x de a doit ombre la variable globale x. b est défini dans une portée où x est connu comme un paramètre de a, de sorte que l'impression fonctionne.

Si vous essayez d'appeler c, cependant, vous obtenez UnboundLocalError: local variable 'x' referenced before assignment puisque Python ne lie pas automatiquement les variables globales. Pour résoudre ce problème, vous devez ajouter global x avant l'affectation.

Votre cas ressemble plus à ceci:

x = 1 
def a(x): 
    print 'a:',x 
    x = 3 
    def b(): 
     x = x 
     print 'b:',x 
    b() 
a(2) 

Pendant l'impression x travaillé dans l'exemple ci-dessus, l'affectation ne fonctionne pas. C'est une mesure de sécurité pour s'assurer que les variables ne fuient pas. La solution est d'utiliser un paramètre par défaut pour « copier » la variable dans le champ d » b:

x = 1 
def a(x): 
    print 'a:',x 
    x = 3 
    def b(x=x): 
     x = x 
     print 'b:',x 
    b() 
a(2) 

Pour résoudre votre problème, vous devez dire Python « faire le paramètre a de make_class visible dans A » et vous devrez le faire avant d'essayer d'affecter le champ a de la classe. Ce n'est pas possible en Python. Si vous pouviez rendre a visible, l'affectation changerait le paramètre, pas le champ, puisque Python n'a aucun moyen de distinguer les deux. Comme vous ne pouvez pas le rendre visible, il n'y a pas de a à lire, d'où le NameError.

Voir here pour une explication de la portée d'un nom en Python.

+2

-1 Vous obtiendrez une erreur de syntaxe avec ce code, car vous ouvrez la classe A et ne pas indenter la ligne suivante. Mettez une ligne de passe indentée et tout ira bien. –

+0

Oups. Ajouté le "passe" manquant. –

Questions connexes