J'ai le besoin de prendre un argument de chaîne et de créer un objet de la classe nommée dans cette chaîne en Python. En Java, j'utiliserais Class.forName().newInstance()
. Existe-t-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 comme nom de classe et l'instancier. En fait, je programme en Jython et instancie des classes Java, d'où le caractère Java de la question. getattr()
fonctionne très bien. Merci beaucoup.
java
python
class
instantiation
Jason
la source
la source
importlib.import
, qui a été rétroporté de python 3 à 2.7 ( docs.python.org/2/library/importlib.html )Réponses:
La réflexion en python est beaucoup plus facile et beaucoup plus flexible qu'en Java.
Je recommande de lire ce tutoriel
Il n'y a pas de fonction directe (que je connaisse) qui prend un nom de classe pleinement qualifié et renvoie la classe, mais vous avez toutes les pièces nécessaires pour construire cela, et vous pouvez les connecter ensemble.
Un petit conseil cependant: n'essayez pas de programmer en style Java lorsque vous êtes en python.
Si vous pouvez expliquer ce que vous essayez de faire, nous pouvons peut-être vous aider à trouver une manière plus pythonique de le faire.
Voici une fonction qui fait ce que vous voulez:
Vous pouvez utiliser la valeur de retour de cette fonction comme s'il s'agissait de la classe elle-même.
Voici un exemple d'utilisation:
Comment ça marche?
Nous utilisons
__import__
pour importer le module qui contient la classe, ce qui nécessitait d'extraire d'abord le nom du module du nom complet. Ensuite, nous importons le module:Dans ce cas,
m
se référera uniquement au module de niveau supérieur,Par exemple, si votre classe vit dans le
foo.baz
module, alorsm
sera le modulefoo
Nous pouvons facilement obtenir une référence à l'
foo.baz
utilisationgetattr( m, 'baz' )
Pour passer du module de niveau supérieur à la classe, il faut utiliser récursivement
gettatr
sur les parties du nom de la classeDisons par exemple, si votre nom de classe est
foo.baz.bar.Model
alors nous faisons ceci:C'est ce qui se passe dans cette boucle:
À la fin de la boucle,
m
sera une référence à la classe. Cela signifie qu'ilm
s'agit en fait de la classe itslef, vous pouvez faire par exemple:la source
__import__
existe. Des projets comme Django qui font du module-loading-magic l'utilisent tout le temps. Bonne réponse.get_class = lambda name: reduce(getattr, name.split('.')[1:], __import__(name.partition('.')[0]))
. Bien que «object.from_name» soit un meilleur nom. Exemples: get_class ('decimal.Decimal'), get_class (nom_module).En supposant que la classe est dans votre portée:
Autrement:
Edit: Notez que vous ne pouvez pas donner un nom tel que «foo.bar» à getattr. Vous devrez le diviser par. et appelez getattr () sur chaque morceau de gauche à droite. Cela permettra de gérer cela:
la source
attrs = 'foo.bar.baz'.split('.'); fooBar = reduce(getattr, attrs[1:], __import__(attrs[0]))
module, _, attrs = 'foo.bar.baz'.partition('.'); fooBar = reduce(getattr, attrs, __import__(module))
Usage
la source
Encore une autre mise en œuvre.
la source
if module_name
LBYL est assez redudant, car l'erreur que vous obtenez si vous supprimez simplement ces lignes est:ValueError: Empty module name
.Il semble que vous abordez cela du milieu au lieu du début. Qu'essayez-vous vraiment de faire? Trouver la classe associée à une chaîne donnée est un moyen d'arriver à une fin.
Si vous clarifiez votre problème, ce qui pourrait nécessiter votre propre refactorisation mentale, une meilleure solution peut se présenter.
Par exemple: essayez-vous de charger un objet enregistré en fonction de son nom de type et d'un ensemble de paramètres? Python épelle cette suppression et vous devriez regarder le module pickle . Et même si le processus de décapage fait exactement ce que vous décrivez, vous n'avez pas à vous soucier de son fonctionnement en interne:
la source
Cela se trouve dans la bibliothèque standard python, sous le nom unittest.TestLoader.loadTestsFromName. Malheureusement, la méthode continue à faire des activités supplémentaires liées aux tests, mais ce premier ha semble réutilisable. Je l'ai modifié pour supprimer la fonctionnalité liée au test:
la source
J'avais besoin d'obtenir des objets pour toutes les classes existantes dans
my_package
. J'importe donc toutes les classes nécessaires dansmy_package
's__init__.py
.Donc, ma structure de répertoires est comme ceci:
Et mon
__init__.py
ressemble à ceci:Ensuite, je crée une fonction comme celle-ci:
Où
module_name = 'my_package'
inspecter doc: https://docs.python.org/3/library/inspect.html#inspect.getmembers
la source