110 votes

Est-ce que python a un équivalent à Java Class.forName ()?

J'ai le besoin de prendre un argument de type chaîne et de créer un objet de la classe nommés dans cette chaîne de caractères en Python. En Java, je voudrais utiliser Class.forName().newInstance(). Est-il un équivalent en Python?


Merci pour les réponses. Pour répondre à ceux qui veulent savoir ce que je fais: je veux utiliser un argument de ligne de commande le nom de la classe, et de l'instancier. Je suis tout à fait de la programmation en Python et l'instanciation des classes Java, d'où la Java " de la question. getattr() fonctionne très bien. Merci beaucoup.

186voto

hasenj Points 36139

La réflexion en python est beaucoup plus facile et beaucoup plus souples que c'est en Java.

Je vous recommande la lecture de ce tutoriel

Il n'y a pas de fonction directe (que je connais) qui prend un nom de classe entièrement qualifié et retourne la classe, cependant, vous avez toutes les pièces nécessaires à la construction, et vous pouvez les connecter entre eux.

Un petit conseil cependant: n'essayez pas de programmer en Java de style lorsque vous êtes en python.

Si vous pouvez expliquer qu'est-ce que vous êtes en train de faire, peut-être nous pouvons vous aider à trouver un plus pythonic façon de faire.

Voici une fonction qui fait ce que vous voulez:

def get_class( kls ):
    parts = kls.split('.')
    module = ".".join(parts[:-1])
    m = __import__( module )
    for comp in parts[1:]:
        m = getattr(m, comp)            
    return m

Vous pouvez utiliser la valeur de retour de cette fonction, comme si c'était la classe elle-même.

Voici un exemple d'utilisation:

>>> D = get_class("datetime.datetime")
>>> D
<type 'datetime.datetime'>
>>> D.now()
datetime.datetime(2009, 1, 17, 2, 15, 58, 883000)
>>> a = D( 2010, 4, 22 )
>>> a
datetime.datetime(2010, 4, 22, 0, 0)
>>> 

Comment cela fonctionne?

Nous utilisons __import__ importer le module qui contient la classe, qui a exigé que nous avons d'abord extraire le nom du module à partir du nom complet. Ensuite, nous importons le module:

m = __import__( module )

Dans ce cas, m ne fait référence qu'à haut niveau module,

Par exemple, si votre classe vit en foo.baz module, alors m sera le module foo
Nous pouvons facilement obtenir une référence à l' foo.baz l'aide getattr( m, 'baz' )

Pour obtenir à partir du niveau supérieur du module de la classe, avoir à utiliser de manière récursive gettatr sur les pièces, le nom de la classe

Disons, par exemple, si vous avez un nom de classe est - foo.baz.bar.Model alors nous n'avons ceci:

m = __import__( "foo.baz.bar" ) #m is package foo
m = getattr( m, "baz" ) #m is package baz
m = getattr( m, "bar" ) #m is module bar
m = getattr( m, "Model" ) #m is class Model

C'est ce qui se passe dans cette boucle:

for comp in parts[1:]:
    m = getattr(m, comp)    

À la fin de la boucle, m sera une référence à la classe. Cela signifie qu' m est en fait la classe itslef, vous pouvez le faire par exemple:

a = m() #instantiate a new instance of the class    
b = m( arg1, arg2 ) # pass arguments to the constructor

30voto

Cody Brocious Points 24042

En supposant que la classe est à votre portée :

Dans le cas contraire :

Edit : Notez que vous ne pouvez pas donner un nom comme « foo.bar » à getattr. Vous devrez diviser par. et appelez getattr() sur chaque morceau de gauche à droite. Il gérera qui :

4voto

grayhemp Points 41

Encore une autre implémentation.

 def import_class(class_string):
    """Returns class object specified by a string.

    Args:
        class_string: The string representing a class.

    Raises:
        ValueError if module part of the class is not specified.
    """
    module_name, _, class_name = class_string.rpartition('.')
    if module_name == '':
        raise ValueError('Class name must contain module part.')
    return getattr(
        __import__(module_name, globals(), locals(), [class_name], -1),
        class_name)
 

2voto

bukzor Points 11085

Ceci est trouvé dans la bibliothèque standard de python, comme unittest. TestLoader.loadTestsFromName. Malheureusement, la méthode continue à faire des activités liées aux tests supplémentaires, mais cela tout d’abord ha ressemble réutilisable. J’ai édité pour enlever les fonctionnalités liées aux tests :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X