web-dev-qa-db-fra.com

Comment créer une nouvelle instance à partir d'un objet de classe dans Python

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!

59
ycseattle

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).

99
xvf17

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)

17
jsbueno

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>
>>>
3
Mike Pennington

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()
2
user99019