J'ai besoin de créer dynamiquement une instance d'une classe en Python. Fondamentalement, j'utilise les modules load_module et inspect pour importer et charger la classe dans un objet de classe, mais je ne vois pas comment créer une instance de cet objet de classe.
S'il vous plaît aider!
J'ai compris la réponse à la question que j'avais posée qui m'a amené à cette page. Comme personne n’a réellement suggéré la réponse à ma question, j’ai pensé la poster.
class k:
pass
a = k()
k2 = a.__class__
a2 = k2()
À ce stade, a et a2 sont tous deux des instances de la même classe (classe k).
Appelez simplement le "type" intégré en utilisant trois paramètres, comme ceci:
ClassName = type("ClassName", (Base1, Base2,...), classdictionary)
mise à jour comme indiqué dans le commentaire ci-dessous, ce n'est pas du tout la réponse à cette question. Je vais le garder non supprimé, car il y a des indices selon lesquels certaines personnes essaient ici de créer de manière dynamique des classes - ce que fait la ligne ci-dessus.
Pour créer un objet d'une classe, il faut aussi une référence, comme dans la réponse acceptée, il suffit d'appeler la classe:
instance = ClassObject()
Le mécanisme d'instanciation est donc:
Python n'utilise pas le mot-clé new
que certains langages utilisent. Son modèle de données explique le mécanisme utilisé pour créer une instance d'une classe lorsqu'elle est appelée avec la même syntaxe que tout autre appelable:
La méthode de sa classe '__call__
Est invoquée (dans le cas d'une classe, sa classe est la "métaclasse" - qui est généralement le type
intégré). Le comportement normal de cet appel consiste à invoquer la méthode (pseudo) statique __new__
Sur la classe en cours d'instanciation, suivie de __init__
. La méthode __new__
Est responsable de l'allocation de mémoire, etc., et est normalement effectuée par le __new__
De object
, qui est la racine de la hiérarchie de classes.
Donc, appeler ClassObject()
appelle ClassObject.__class__.call()
(qui sera normalement type.__call__
) Cette méthode __call__
Recevra ClassObject lui-même comme premier paramètre - un Pure Python ressemblerait à ceci: (la version de cPython est bien sûr, réalisée en C, et avec beaucoup de code supplémentaire pour les casse et les optimisations)
class type:
...
def __call__(cls, *args, **kw):
constructor = getattr(cls, "__new__")
instance = constructor(cls) if constructor is object.__new__ else constructor(cls, *args, **kw)
instance.__init__(cls, *args, **kw)
return instance
(Je ne me souviens pas d'avoir vu sur la documentation la justification exacte (ou le mécanisme) de supprimer des paramètres supplémentaires à la racine __new__
Et de les transmettre à d'autres classes - mais c'est ce qui arrive "dans la vie réelle" - si object.__new__
Est appelé avec tous les paramètres supplémentaires, il génère une erreur de type - toutefois, toute implémentation personnalisée d'un __new__
Obtiendra les paramètres supplémentaires normalement)
Voici comment créer dynamiquement une classe nommée Child
dans votre code, en supposant que Parent
existe déjà ... même si vous n’avez pas de classe explicite Parent
, vous pourrait utiliser object
...
Le code ci-dessous définit __init__()
, puis l’associe à la classe.
>>> child_name = "Child"
>>> child_parents = (Parent,)
>>> child body = """
def __init__(self, arg1):
# Initialization for the Child class
self.foo = do_something(arg1)
"""
>>> child_dict = {}
>>> exec(child_body, globals(), child_dict)
>>> childobj = type(child_name, child_parents, child_dict)
>>> childobj.__name__
'Child'
>>> childobj.__bases__
(<type 'object'>,)
>>> # Instantiating the new Child object...
>>> childinst = childobj()
>>> childinst
<__main__.Child object at 0x1c91710>
>>>
Si vous avez un module avec une classe que vous souhaitez importer, vous pouvez le faire comme ceci.
module = __import__(filename)
instance = module.MyClass()
Si vous ne connaissez pas le nom de la classe, vous pouvez parcourir les classes disponibles dans un module.
import inspect
module = __import__(filename)
for c in module.__dict__.values():
if inspect.isclass(c):
# You may need do some additional checking to ensure
# it's the class you want
instance = c()