Forum Programmation.python Instancier un classe dérivée à partir d'une instance de la classe de base déjà instanciée.

Posté par  .
Étiquettes : aucune
0
14
mai
2009
Bonjour,

J'explique mon problème.
J'ai créer une classe fille de la classe lxml.etree.Element, appelons la MyElement, qui rajoute de nouvelles méthodes et un nouvel attribut.

J'aimerais instancier un objet de type MyElement à partir d'un objet de type Element existant, comme ceci:

elem = Element()
myElem = MyElement(elem)

et pouvoir accéder aux attributs et méthodes de Element.

Est ce que quelqu'un sait comment faire ?
  • # Monkey patching ?

    Posté par  . Évalué à 3.

    Tu peut faire du monkey patching comme ceci:
    elem.__class__.__bases__ += (MyElement, )

    Ou alors passer par la composition.

    Ou encore invoquer tes méthodes comme suit:
    MyElement.ma_methode(elem, arg1, arg2)

    J'ai peut être une autre idée mais je vais d'abord vérifier avant de la poster.
    • [^] # Re: Monkey patching ?

      Posté par  . Évalué à 4.

      Oui donc en fait tu peut faire ceci:

      elem.__class__ = Myelement
      • [^] # Re: Monkey patching ?

        Posté par  . Évalué à 1.

        Merci beaucoup.
        Je vais réussir à me débrouiller avec.
        • [^] # Re: Monkey patching ?

          Posté par  . Évalué à 1.

          En faite la classe Element de lxml.etree n'est pas une classe 'new-style':

          node.__class__ = MyNode
          TypeError: __class__ must be set to new-style class, not 'classobj' object

          Il n'existe pas le même genre de mécanisme avec les vieilles classes ?
          Pour info j'utilise python 2.5.2 (celui par défaut sur la distrib).
          • [^] # Re: Monkey patching ?

            Posté par  . Évalué à 3.

            Bon je viens de regarder de près et si je ne dit pas de bétises le problème n'est pas que ça soit une vielle classe mais que lxml est un binding pour la libxml les types sont donc codés en C et il n'est pas possible de les monkey patcher. La seule solution que je voit c'est la composition comme ceci:
            class MyNode(object):
            def __init__(self, node):
            self._node = node
            def __getattr__(self, name):
            return getattr(self._node, name)
            def __setattr__(self, name, value):
            if hasattr(self._node, name):
            setattr(self._node, name, value)
            else:
            setattr(self, name, value)
            # tes methodes persos


            PS: désolé pour le formatage
            • [^] # Re: Monkey patching ?

              Posté par  . Évalué à 1.

              Alors, j'ai essayé en rajoutant les méthodes de MyNode à Element:

              mynode = MyNode()
              for attribute in dir(mynode):
                  if attribute.startswith('_'):
                      continue
                  setattr(node, attribute, getattr(mynode, attribute))


              Mais j'obtiens cette erreur (alors que ça fonctionnait avec deux classes bidons lors de tests):
                File svgnode.py, line 47, in convertToMyNode
                  setattr(node, attribute, getattr(mynode, attribute))
              AttributeError: 'lxml.etree._Element' object has no attribute 'checkNamespace'


              J'ai essaye avec ta technique, mais j'obtiens une boucle infini sur le setattr quand dans le __init__ on fait le:
              self._node = node


              Finalement, ça fonctionne en faisant:
              def __init__(self, node):
                  self._node = node

              def __getattr__(self, name):
                  if name in self.__dict__:
                      return self.__dict__[name]
                  elif '_node' in self.__dict__:
                      return getattr(self._node, name)
                  else:
                      return None

              def __setattr__(self, name, value):
                  if name not in self.__dict__:
                      self.__dict__[name] = value
                  else:
                      if hasattr(self._node, name):
                          setattr(self._node, name, value)
                      else:
                          setattr(self, name, value)


              Merci pour tout.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.