Bonjour,

J'ai une classe D dérivant de object et de collections.defaultdict, dont je redéfinis le __setitem__. Je voudrais que sur une clef manquante, defaultdict.__setitem__ soit appelé, plutot que D.__setitem__ (car defaultdict.__getitem__ appelle __setitem__ sur une clef manquante ).

Je ne veux pas surcharger D.__getitem__ pour des raisons de performance.

Que pensez-vous de la solution suivante ?
J'espère que la fonction générant les __missing__ est appelée uniquement "au bon moment".

Merci d'avance

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 
from collections import defaultdict
from itertools import repeat
 
class UseDefaultDictGetItem(defaultdict,object):
    __getitem__ = defaultdict.__getitem__
 
class shield:
    def __init__(self,obj):
        self.obj=obj
    def __enter__(self):
        assert self.obj.shield
        self.obj.shield= False
        self.temp= self.obj.__class__           
        self.obj.__class__= UseDefaultDictGetItem
        return self
    def __exit__(self, type, value, traceback):
        assert not(self.obj.shield), "state discrepancy, (don't call the __missing__, don't use threads?)"
        assert self.temp, "no class to setback"
        self.obj.__class__= self.temp# self.obj._basicclass
 
class D(defaultdict,object):
    """ Redirects [missing.__setattr__] to defaultdict """
    def shieldDefault(self): self.shield= True # returns None for dd.__init__()
    def __init__(self, ):
        #self._basicclass= self.__class__
        self.shield= False
        self.lock= shield(self)
        defaultdict.__init__(self, self.shieldDefault )#repeat(None).next)
    def __setitem__(self, k,v):
        if self.shield:            
            with self.lock: self[k]=v #v= defaultdict.__setitem__(self, k,v) #defaultdict ne marche pas                                                               
        else:            
            print " CALLS D.setitem"
            defaultdict.__setitem__(self, k,v)
 
if __name__ == '__main__':
    y= D()    
    print "y[0]:"
    print y[0] # D.__setitem__ n'est pas appelé (valeur manquante)
    print "set et y[0]:"
    y[0]=1
    print y[0] # D.__setitem__ est appelé (key presente)