IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

defaultdict: changer __setitem__ sur une instance


Sujet :

Python

  1. #1
    Membre Expert
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Par défaut defaultdict: changer __setitem__ sur une instance
    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)

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Je n'ai pas encore tout compris mais en lisant le 'besoin' en français, je me demande pourquoi faire plus compliqué que çà:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    cclass foo(dict):
        def __missing__(self, k):
            print ('__missing__')
            dict.__setitem__(self, k, None) 
     
    class D(foo):
        def __setitem__(self, k, v):
            print ('__setitem__')
            return foo.__setitem__(self, k, v)

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour,

    J'ai trois questions.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        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)
    Vu que l'on hérite de defaultdict que l'on écrive defaultdict.__setitem__(self, k, v) ou self[k] = v de toute manière c'est D.__setitem__ qui est utilisé, donc c'est le __setitem__ de defaultdict qui est utiliser: Ou est le tour de passe passe ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    class UseDefaultDictGetItem(defaultdict, object):
    class D(defaultdict, object):
    Pourquoi hériter de object ?

    Ce n'est pas compliquer inutilement la chose ?

    @+

  4. #4
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Hello,

    J'ai une autre question, tu parles beaucoup de performances dans tes posts, perso je trouve ça en contradiction avec la POO, ne ferais-tu pas fausse route?

  5. #5
    Membre Expert
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Par défaut
    Merci beaucoup pour vos réponses

    pourquoi faire plus compliqué que çà
    Effectivement, __missing__ est bien mieux dans mon cas !

    *Pourquoi hériter de object-> J'ai besoin de descripteurs sur D

    * Ou est le tour de passe passe
    En se servant du else comme un Hook. Par exemple ici, send_message_reseau()- la version surchargée par D de __setitem__ - n'est pas appelée depuis defaultdict.__getitem__.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    if self.shield:            
                with self.lock:
                    self[k] = v  # v = defaultdict.__setitem__(self, k, v) #defaultdict ne marche pas                                                               
            else: # HOOK: overloaded setitem            
                send_message_reseau(self,k,v)
    @fred: Bah mon code utilise la POO, mais après profiling, j'essaye d'améliorer la situation.

  6. #6
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour,

    Citation Envoyé par VV33D Voir le message
    *Pourquoi hériter de object-> J'ai besoin de descripteurs sur D
    ? C'est à dire ? De quoi avez vous besoin pour D que vous n'ayez besoin de cet héritage ?

    Citation Envoyé par VV33D Voir le message
    * Ou est le tour de passe passe
    En se servant du else comme un Hook. Par exemple ici, send_message_reseau()- la version surchargée par D de __setitem__ - n'est pas appelée depuis defaultdict.__getitem__.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    if self.shield:            
                with self.lock:
                    self[k] = v  # v = defaultdict.__setitem__(self, k, v) #defaultdict ne marche pas                                                               
            else: # HOOK: overloaded setitem            
                send_message_reseau(self,k,v)
    Voila qui ne vas pas arranger ma compréhension...
    Pour moi self[k] = v fait appel au __setitem__ de defaultdict.

    @+

  7. #7
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par PauseKawa Voir le message
    Pour moi self[k] = v fait appel au __setitem__ de defaultdict.
    Pour ce que j'en ai compris, la question est d'éviter de passer par D.__setitem__ lorsqu'on initialise la clé, pour éviter le délai d'acquisition du verrou... mais comme "verrou" = multithreads (au moins dans ma tête), c'est plutôt "dangereux".
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #8
    Membre Expert
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Par défaut
    Le but de la classe D est:
    1/ setitem envoie un message réseau à la place de setitem sur self
    2/ mais je veux éviter ce comportement lorsque je getitem une clef absente
    3/ Dériver de objet pour avoir les descripteurs (pour un tout autre besoin)

    Le verrou est la uniquement pour bien remettre dans le bon état self.__class__ en cas d'exception (d'ailleurs il ne serait pas adéquat dans un contexte threadé), j'aurais du l'appeler self.shielder

  9. #9
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour,

    Citation Envoyé par VV33D Voir le message
    1/ setitem envoie un message réseau à la place de setitem sur self
    2/ mais je veux éviter ce comportement lorsque je getitem une clef absente
    3/ Dériver de objet pour avoir les descripteurs (pour un tout autre besoin
    Ok pour 1/2 : l'exemple avec self[k] = v est trompeur.

    Mais pour 3... En quoi dériver d'object permet d'avoir les descripteurs ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    >>> dir(object)
    ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
    J'ai louper un passage ?
    Et même : Dashed Arrow Up Rule.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    >>> isinstance(defaultdict, object)
    True
    @+

  10. #10
    Membre Expert
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Par défaut
    Il me semble qu'en py26, les descripteurs seront appelés seulement si la classe dérive de object

  11. #11
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Python 2.6.7 (r267:88850, Aug 11 2011, 12:16:10) 
    [GCC 4.6.1] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from collections import defaultdict
    >>> isinstance(defaultdict, object)
    True
    Mais bon... Ce qui me semble 'évident' n'est peut être pas 'juste'.

  12. #12
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par VV33D Voir le message
    Le but de la classe D est:
    1/ setitem envoie un message réseau à la place de setitem sur self
    2/ mais je veux éviter ce comportement lorsque je getitem une clef absente
    3/ Dériver de objet pour avoir les descripteurs (pour un tout autre besoin)

    Le verrou est la uniquement pour bien remettre dans le bon état self.__class__ en cas d'exception (d'ailleurs il ne serait pas adéquat dans un contexte threadé), j'aurais du l'appeler self.shielder
    La lecture de cela me ferait plutôt écrire deux classes R et D avec un changement d'état pour passer de l'un à l'autre:
    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
    class foo(dict):
        def __missing__(self, k):
            print ('%s: __missing__' % self.__class__.__name__)
            dict.__setitem__(self, k, None) 
     
    class D(foo):
        def __setitem__(self, k, v):
            print ('D: __setitem__')
            return foo.__setitem__(self, k, v)
     
    class R(foo):
        def __setitem__(self, k, v):
            print ('R: __setitem__')
            # send_message_reseau(self,k,v)
     
    if __name__ == '__main__':
        e = foo()
        ix = 0
        for cls in (D, R):
            e.__class__ = cls
            print (e[ix])
            ix += 1
            e[ix] = 1
            print (e[ix])
            ix += 1
    Mais vous devez avoir de bonnes raisons pour avoir une seule classe avec des if...then...else dans la méthode __setitem__
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  13. #13
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour,

    Citation Envoyé par PauseKawa Voir le message
    J'ai louper un passage ?
    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    #!/usr/bin/python
    # -*- coding: UTF-8 -*-
    #
    #
    class D(object):
        """exemple générique"""
        def __init__(self, name='default', value='0'):
            self.name = name
            self.value = value
     
        def __get__(self, obj, objtype):
            print '__get__', self.name
            return self.value
     
        def __set__(self, obj, val):
            print '__set__', self.name
            self.value = val
     
     
    class D1:
        """exemple générique"""
        def __init__(self, name='default', value='0'):
            self.name = name
            self.value = value
     
        def __get__(self, obj, objtype):
            print '__get__', self.name
            return self.value
     
        def __set__(self, obj, val):
            print '__set__', self.name
            self.value = val
     
     
    class A:
        v = D("a_name", 10)
     
     
    class B(object):
        v = D("b_name", 20)
     
    class C(object):
        v = D1("c_name", 30)
     
     
    a = A()
    print a.v
    a.v = 10
    print a.v
    b = B()
    print b.v
    b.v = 20
    print b.v
    c = C()
    print c.v
    c.v = 30
    print c.v
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    __get__ a_name
    10
    10
    __get__ b_name
    20
    __set__ b_name
    __get__ b_name
    20
    <__main__.D1 instance at 0xb7753fec>
    30
    Oui.

    @+

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 20/02/2009, 10h36
  2. problème de connexion sur une instance 9i
    Par abadana dans le forum Administration
    Réponses: 1
    Dernier message: 19/12/2008, 18h26
  3. Satistiques sur une instance
    Par loulag07 dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 23/04/2008, 15h20
  4. Réponses: 4
    Dernier message: 14/09/2007, 08h41
  5. Réponses: 1
    Dernier message: 18/07/2007, 17h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo