2010-02-09 6 views
16

J'ai donc un ensemble de classes et une chaîne avec l'un des noms de classe. Comment est-ce que j'instancie une classe basée sur cette chaîne?Instancier une classe Python à partir d'un nom

class foo: 
    def __init__(self, left, right): 
    self.left = left 
    self.right = right 

str = "foo" 
x = Init(str, A, B) 

Je veux que x soit une instanciation de classe foo.

+2

Dupliquer. http://stackoverflow.com/questions/734970/python-reference-to-a-class-from-a-string, http://stackoverflow.com/questions/1176136/convert-string-to-python-class- objet, http://stackoverflow.com/questions/553784/can-you-use-a-string-to-instantiate-a-class-in-python, etc. –

Répondre

13

Si vous connaissez l'espace de noms impliqué, vous pouvez l'utiliser directement - par exemple, si toutes les classes sont dans le module zap, le dictionnaire vars(zap) est cet espace de noms; Si elles sont toutes dans le module en cours, globals() est probablement le moyen le plus pratique d'obtenir ce dictionnaire. Si les classes ne sont pas toutes dans le même espace de noms, construire un espace de noms "artificiel" (une dictée dédiée avec des noms de classe comme clés et objets de classe comme valeurs), comme le suggère @Ignacio, est probablement l'approche la plus simple.

6
classdict = {'foo': foo} 

x = classdict['foo'](A, B) 
+2

Comment puis-je le faire en utilisant la réflexion? – klynch

+0

Vous pouvez * utiliser 'getattr()', mais cela pourrait vous exposer à des problèmes de sécurité. L'utilisation d'un décorateur de classe vous permettra d'énumérer automatiquement les classes, mais celles-ci n'existent que dans les nouvelles versions de Python. –

+0

Comment utiliseriez-vous le décorateur?Serait-il ajouter à une liste de classes instanciables - et je devrais parcourir cette liste pour choisir la bonne classe à instancier? –

15

Dans votre cas, vous pouvez utiliser quelque chose comme

get_class = lambda x: globals()[x] 
c = get_class("foo") 

Et il est encore plus facile aucune classe get à partir du module

import somemodule 
getattr(somemodule, "SomeClass") 
2
classname = "Foo" 
foo = vars()[classname](Bar, 0, 4) 

Ou peut-être

def mkinst(cls, *args, **kwargs): 
    try: 
     return globals()[cls](*args, **kwargs) 
    except: 
     raise NameError("Class %s is not defined" % cls) 

x = mkinst("Foo", bar, 0, 4, disc="bust") 
y = mkinst("Bar", foo, batman="robin") 

Notes diverses sur l'extrait:

*args et **kwargs sont des paramètres spéciaux en Python, ils veulent dire «un tableau de args non-mots» et «un dict de mot-clé args »en conséquence.

PEP-8 (guide officiel de style Python) recommande d'utiliser cls pour les variables de classe.

vars() renvoie une dict de variables définies dans la portée locale.

globals() renvoie un dict de variables actuellement présentes dans l'environnement en dehors de la portée locale.

1

Vous pourriez envisager l'utilisation de métaclasse ainsi:

Cls = type('foo',(), foo.__dict__) 
x = Cls(A, B) 

Pourtant, il crée une autre classe similaire.

Questions connexes