2011-05-15 4 views
2

Je souhaite écrire une classe qui sous-classe la liste Python et notifie un autre objet lorsque la liste change. Comme il existe de nombreuses méthodes qui ont besoin d'être surchargée, j'ai opté pour une solution comme celui-ci, au lieu de passer outre toutes les méthodes qui modifient la liste:Remplacement des méthodes spéciales d'un objet de liste Python

destructiveMethods = ["__setitem__", 
         "__setslice__", 
         "__delitem__", 
         "__delslice__", 
         "append", 
         "extend", 
         "remove", 
         "reverse", 
         "sort"] 

class OwnedList(list): 
    def __init__(self, owner, initValue=[]): 
     super(OwnedList, self).__init__(initValue) 


     def wrappedMethod(method): 
      def resultMethod(*args, **kwargs): 
       ret = method(*args, **kwargs) 
       self.owner.notify() 
       return ret 
      return resultMethod 

     self.owner = owner 
     for m in destructiveMethods: 
      setattr(self, m, wrappedMethod(getattr(self, m))) 

Cela fonctionne pour des méthodes comme « ajouter » mais pas des méthodes spéciales comme "__setitem__". Pour ceux, je reçois simplement les anciennes méthodes.

J'ai remarqué que si j'imprime la valeur de, disons, ajouter, je reçois quelque chose comme:

<built-in method append of list object at 0x267a7a0> 

Mais pour __setitem__ (sur une liste de vanille) ce que je reçois:

<method-wrapper '__setitem__' of list object at 0x266fd40> 

Peut-être que cela a quelque chose à voir avec mon problème.

Toute aide est appréciée. Si vous connaissez une meilleure façon d'accomplir ce que je dois faire, partagez vos idées sur ce point. Merci.

MISE À JOUR: Autre chose que j'ai remarqué appelle __setitem__ directement sur un objet OwnedList fonctionne comme prévu, mais en utilisant les supports ne fonctionne pas.

Répondre

2

Les méthodes spéciales ne peuvent être définies que sur le type de l'objet et non sur les instances source.

Comparer

>>> class A(object): 
...  __getitem__ = lambda self,i: 42 
>>> A()[0] 
42 

et

>>> class B(object): 
...  def __init__(self): 
...    self.__getitem__ = lambda self,i: 42 
>>> B()[0] 
TypeError: 'B' object does not support indexing 

Vous devez adapter A, à savoir définir directement vos méthodes spéciales dans le corps de la classe et non dans le constructeur.

+0

Merci. Fonctionne comme un charme. – Elektito

Questions connexes