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 :

setdefault dictionary method


Sujet :

Python

  1. #1
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 26
    Par défaut setdefault dictionary method
    Salut a tout le monde..
    je voudrais savoir s'il est possible de reecrir le code suivant sans la methode "setdefault".. je debute en programmation...

    merci d'avance

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class classifier:
      def __init__(self):
        self.wx={ }
     
     
     def aug (self,item, kateg):
        self.wx.setdefault(item,{})
        self.wx[item].setdefault(kateg,0)
        self.wx[item][kateg]+=1

  2. #2
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 067
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 067
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class classifier(dict):
    	''
    	def aug(self,item,kateg):
    		if not item in self: self[item]={kateg:0}
    		else: self[item][kateg]+=1

  3. #3
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 26
    Par défaut
    Salut,
    Si j ai bien compris on a plus besoin d initialiser le 'dict'?
    merci

  4. #4
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 067
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 067
    Par défaut
    tu veux dire: 'pourquoi j'ai viré le __init__ ?'
    puisque le seul attribut est un dict, autant dériver d'un dict.

  5. #5
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 26
    Par défaut
    ok, et si je veux initialiser un autre variable en plus du 'dict'

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Bien vu josmiley pour l’héritage de dict, je n’y avais même pas pensé.



    Par contre, j’ai bien l’impression qu’il faut dans tous les cas d’héritage, même d’un type de base comme dict, exécuter la fonction __init__ de la classe parente dans la définition de la classe fille.


    De plus , comparer:

    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
    class classifierAzzuri:
        def __init__(self):
            self.wx={ }
     
        def aug (self,item, kateg):
            self.wx.setdefault(item,{})
            self.wx[item].setdefault(kateg,0)
            self.wx[item][kateg]+=1
     
    print 'Azzuri'
    dAzz = classifierAzzuri()
    dAzz.aug('a',980)
    print dAzz.wx
    dAzz.aug('a',500)
    print dAzz.wx
     
    print
    class classifierjo(dict):
        ''
        def aug(self,item,kateg):
            if not item in self: self[item]={kateg:0}
            else: self[item][kateg]+=1
     
    print 'josmiley' 
    djo = classifierjo()
    djo.aug('A',1300)
    print djo
    djo.aug('A',700)
    print djo

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Azzuri
    {'a': {980: 1}}
    {'a': {500: 1, 980: 1}}
     
    josmiley
    {'A': {1300: 0}}
     
    Traceback (most recent call last):
      File "C:\Python27\dicow.py", line 40, in <module>
        djo.aug('A',700)
      File "C:\Python27\dicow.py", line 34, in aug
        else: self[item][kateg]+=1
    KeyError: 700




    Voilà pourquoi je propose:

    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
    class classifier1(dict):
        def __init__(self):
            dict.__init__(self)
        def aug(self,item,kateg):
            if item not in self:
                self[item]={kateg:1}
            elif kateg not in self[item]:
                self[item][kateg] = 1
            else:
                self[item][kateg]+=1
     
    dw = classifier1()
    dw.aug('a',900)
    dw.aug('b',1900)
    print dw
    dw.aug('a','sup')
    print dw
    dw.aug('a','sup')
    print dw
    print 
     
     
    class classifier2(dict):
        def __init__(self):
            dict.__init__(self)
        def aug(self,item,kateg):
            try:
                self[item][kateg]+=1
            except KeyError:
                try:
                    self[item][kateg] = 1
                except KeyError:
                    self[item]={kateg:1}
     
    zw = classifier2()
    zw.aug('A',443)
    zw.aug('B',887)
    print zw
    zw.aug('A','gol')
    print zw
    zw.aug('A','gol')
    print zw
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    {'a': {900: 1}, 'b': {1900: 1}}
    {'a': {900: 1, 'sup': 1}, 'b': {1900: 1}}
    {'a': {900: 1, 'sup': 2}, 'b': {1900: 1}}
     
    {'A': {443: 1}, 'B': {887: 1}}
    {'A': {'gol': 1, 443: 1}, 'B': {887: 1}}
    {'A': {'gol': 2, 443: 1}, 'B': {887: 1}}
    Cf les considérations attachées au premier exemple dans la page
    http://www.python.org/download/relea....3/descrintro/




    ok, et si je veux initialiser un autre variable en plus du 'dict'
    Prière d’être plus compréhensible

  7. #7
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    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 699
    Par défaut
    Salut,
    Par contre, j’ai bien l’impression qu’il faut dans tous les cas d’héritage, même d’un type de base comme dict, exécuter la fonction __init__ de la classe parente dans la définition de la classe fille.
    Ce qui se traduit par:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class classifier2(dict):
        def __init__(self):
            dict.__init__(self)


    En fait, propriété magique de l'héritage, il n'est pas nécessaire de déclarer __init__ 'seulement' pour que l'__init__ du parent soit appelé...
    Il ne faut le faire que parce qu'il est utile d'y faire quelque chose qui motive la déclaration d'un __init__ et dans ce cas, il ne faut pas oublier que le parent doit aussi être initialisé.

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

  8. #8
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 26
    Par défaut
    Citation Envoyé par eyquem Voir le message
    Bien vu josmiley pour l’héritage de dict, je n’y avais même pas pensé.



    Par contre, j’ai bien l’impression qu’il faut dans tous les cas d’héritage, même d’un type de base comme dict, exécuter la fonction __init__ de la classe parente dans la définition de la classe fille.


    De plus , comparer:

    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
    class classifierAzzuri:
        def __init__(self):
            self.wx={ }
     
        def aug (self,item, kateg):
            self.wx.setdefault(item,{})
            self.wx[item].setdefault(kateg,0)
            self.wx[item][kateg]+=1
     
    print 'Azzuri'
    dAzz = classifierAzzuri()
    dAzz.aug('a',980)
    print dAzz.wx
    dAzz.aug('a',500)
    print dAzz.wx
     
    print
    class classifierjo(dict):
        ''
        def aug(self,item,kateg):
            if not item in self: self[item]={kateg:0}
            else: self[item][kateg]+=1
     
    print 'josmiley' 
    djo = classifierjo()
    djo.aug('A',1300)
    print djo
    djo.aug('A',700)
    print djo

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Azzuri
    {'a': {980: 1}}
    {'a': {500: 1, 980: 1}}
     
    josmiley
    {'A': {1300: 0}}
     
    Traceback (most recent call last):
      File "C:\Python27\dicow.py", line 40, in <module>
        djo.aug('A',700)
      File "C:\Python27\dicow.py", line 34, in aug
        else: self[item][kateg]+=1
    KeyError: 700




    Voilà pourquoi je propose:

    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
    class classifier1(dict):
        def __init__(self):
            dict.__init__(self)
        def aug(self,item,kateg):
            if item not in self:
                self[item]={kateg:1}
            elif kateg not in self[item]:
                self[item][kateg] = 1
            else:
                self[item][kateg]+=1
     
    dw = classifier1()
    dw.aug('a',900)
    dw.aug('b',1900)
    print dw
    dw.aug('a','sup')
    print dw
    dw.aug('a','sup')
    print dw
    print 
     
     
    class classifier2(dict):
        def __init__(self):
            dict.__init__(self)
        def aug(self,item,kateg):
            try:
                self[item][kateg]+=1
            except KeyError:
                try:
                    self[item][kateg] = 1
                except KeyError:
                    self[item]={kateg:1}
     
    zw = classifier2()
    zw.aug('A',443)
    zw.aug('B',887)
    print zw
    zw.aug('A','gol')
    print zw
    zw.aug('A','gol')
    print zw
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    {'a': {900: 1}, 'b': {1900: 1}}
    {'a': {900: 1, 'sup': 1}, 'b': {1900: 1}}
    {'a': {900: 1, 'sup': 2}, 'b': {1900: 1}}
     
    {'A': {443: 1}, 'B': {887: 1}}
    {'A': {'gol': 1, 443: 1}, 'B': {887: 1}}
    {'A': {'gol': 2, 443: 1}, 'B': {887: 1}}
    Cf les considérations attachées au premier exemple dans la page
    http://www.python.org/download/relea....3/descrintro/





    Prière d’être plus compréhensible
    Initialiser deux variavles d'instance comme suit :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class azzuri :
        def __init__(self):
          # initialise deux variables d'instance wx et wy
           self.wx = { }
           self.wy = { }
           def aug(self,item,classe):
              self.wx.setdefault( item ,{} )
              self.wx[item].setdefault(classe,0)
              self.wx[item][classe]+=1
     
           def aug1(self,classe):
              self.wy.setdefault(classe,0)
              self.wy[ classe ] +=1

  9. #9
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class classifier2(dict):
        def __init__(self):
            dict.__init__(self)
    C'est aussi valable pour
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class classifier1(dict):
        def __init__(self):
            dict.__init__(self)
    aussi, alors.

    Merci pour cette correction. Je n’avais pas les idées claires sur ce point.



    -----------------------------------


    Plutôt que les codes à plusieurs lignes vus plus haut, il y a une autre possibilité: utiliser defaultdict du module collections


    Appliqué à la définition de wx et wy, ça donne le code suivant.
    J’y ai écrit une fonction aug() commune pour l’ajout dans wx aussi bien que dans wy sans avoir à faire attention d’écrire une fonction aug() spécifique à chaque fois.
    Remarquer que la classe azzuri n'hérite d'aucune classe

    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
    from collections import defaultdict
     
    class azzuri:
        def __init__(self):
            self.wx = defaultdict(lambda : defaultdict(int))
            self.wy = defaultdict(int)
     
        def aug(self,*arg):
            if len(arg)==1:
                self.wy[arg[0]] += 1
            elif len(arg)==2:
                self.wx[arg[0]][arg[1]] += 1
     
     
    dik = azzuri()
    print 'dik.wx :',dik.wx
    print 'dik.wy :',dik.wy
    print '-----'
    dik.aug(34,'qw')
    dik.aug('kili')
    dik.aug(887,'balance')
    dik.aug(34,'hoof')
    dik.aug(34,'qw')
    dik.aug('plage')
    dik.aug('kili')
    print 'dik.wx :\n',dik.wx
    print
    print 'dik.wy :\n',dik.wy
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    dik.wx : defaultdict(<function <lambda> at 0x010A1AB0>, {})
    dik.wy : defaultdict(<type 'int'>, {})
    -----
    dik.wx :
    defaultdict(<function <lambda> at 0x010A1AB0>, {34: defaultdict(<type 'int'>, {'hoof': 1, 'qw': 2}), 887: defaultdict(<type 'int'>, {'balance': 1})})
     
    dik.wy :
    defaultdict(<type 'int'>, {'plage': 1, 'kili': 2})




    Mais la façon particulière de s’afficher qu’a defaultdict rend peu agréable la lecture d’un tel dictionnaire.

    Voici donc un code dans lequel la définition d’attributs affx et affy , qui ne servent qu’à pouvoir appeler __getattribute__(self,name) avec un name égal à ’affx’ ou ’affy’ , permet d’obtenir un affichage plus lisible.
    La classe azzuri hérite de object.

    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
    from collections import defaultdict
     
    class azzuri(object):
        def __init__(self):
            self.wx = defaultdict(lambda : defaultdict(int))
            self.wy = defaultdict(int)
            self.affx = '{}'
            self.affy = '{}'
     
        def aug(self,*arg):
            if len(arg)==1:
                self.wy[arg[0]] += 1
            elif len(arg)==2:
                self.wx[arg[0]][arg[1]] += 1
     
        def __getattribute__(self,name):
            if name=='affx':
                return dict((k,dict(di)) for k,di in self.wx.iteritems())
            elif name=='affy':
                return dict(self.wy)
            else:
                return object.__getattribute__(self,name)
     
        def __repr__(self):
            return 'dik.wx = '+repr(self.affx)+'\ndik.wy = '+repr(self.affy)
     
    dik = azzuri()
    print 'dik.affx =',dik.affx
    print 'dik.affy =',dik.affy
    print
    print'dik :\n',dik
    print '-----'
    dik.aug(34,'qw')
    dik.aug('kili')
    dik.aug(887,'balance')
    dik.aug(34,'hoof')
    dik.aug(34,'qw')
    dik.aug('plage')
    dik.aug('kili')
    print 'dik.affx =',dik.affx
    print
    print 'dik.affy =',dik.affy
    print
    print'dik :\n',dik
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    dik.affx = {}
    dik.affy = {}
     
    dik :
    dik.wx = {}
    dik.wy = {}
    -----
    dik.affx = {34: {'hoof': 1, 'qw': 2}, 887: {'balance': 1}}
     
    dik.affy = {'plage': 1, 'kili': 2}
     
    dik :
    dik.wx = {34: {'hoof': 1, 'qw': 2}, 887: {'balance': 1}}
    dik.wy = {'plage': 1, 'kili': 2}








    Enfin, pour pouvoir se passer des attributs artificiels affx et affy, et écrire directement dik.wx et dik.wy, il faut (comme dans le code précédent d’ailleurs) faire appel à object.__getattribute__(self,name) pour éviter une boucle infinie dans l’appel des attributs.
    La classe azzuri hérite de object.

    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
    from collections import defaultdict
     
    class azzuri(object) :
        def __init__(self):
            self.wx = defaultdict(lambda: defaultdict(int))
            self.wy = defaultdict(int)
     
        def aug(self,*arg):
            if   len(arg)==2:  object.__getattribute__(self, 'wx')[arg[0]][arg[1]] += 1
            elif len(arg)==1:  object.__getattribute__(self, 'wy')[arg[0]] += 1
            else:  print 'Il ne peut pas y avoir plus de deux arguments'
     
        def __getattribute__(self,name):
            if name=='wx':
                return dict((k,dict(di))
                            for k,di in object.__getattribute__(self, name).iteritems())
            if name=='wy':
                return dict(object.__getattribute__(self, name))
     
            if name=='aug':
                return object.__getattribute__(self, name)
     
        def __repr__(self):
            return 'dik.wx = '+repr(self.wx)+'\ndik.wy = '+repr(self.wy)
     
     
    dik = azzuri()
    print 'dik.wx :',dik.wx
    print 'dik.wy :',dik.wy
    print
    print 'dik :\n',dik
    print '-----'
    dik.aug(34,'qw')
    dik.aug('kili')
    dik.aug(887,'balance')
    dik.aug(34,'hoof')
    dik.aug(34,'qw')
    dik.aug('plage')
    dik.aug('kili')
    print
    print 'dik :\n',dik
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    dik.wx : {}
    dik.wy : {}
     
    dik :
    dik.wx = {}
    dik.wy = {}
    -----
     
    dik :
    dik.wx = {34: {'hoof': 1, 'qw': 2}, 887: {'balance': 1}}
    dik.wy = {'plage': 1, 'kili': 2}


    Dans les deux derniers codes, j’ai fait hériter la classe azzuri de object car il me semble que de toutes façons
    c’est à ce niveau qu’un defaultdict.__getattribute__(self,name)
    ou un
    dict.__getattribute__(self,name)
    vient chercher la fonction __getattribute__



    Mais si on fait hériter de dict ou defaultdict,
    et quelle que soit l’écriture defaultdict.__getattribute__(self,name)
    ou
    dict.__getattribute__(self,name)
    qu’on utilise, les 2 derniers progammes marchent aussi bien l’un que l’autre



    Je n’ai pas non plus écrit de dict.__init__() ou defaultdict.__init__() ou object.__init__()


    J’avoue que je ne sais vraiment pas ce qui devrait permettre de décider de telle ou telle écriture. À ce niveau là, je bidouille , les programmes marchent mais ça ne me plait guère.

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 99
    Par défaut
    Hmm juste pour reprendre la réponse initiale. Il a une erreur dans l'exemple.
    Citation Envoyé par josmiley Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class classifier(dict):
    	''
    	def aug(self,item,kateg):
    		if not item in self: self[item]={kateg:0}
    		else: self[item][kateg]+=1

    Si l'on fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    c = classifier()
    c.aug("1", "3")
    c.aug("1", "4")
    On va avoir une exception parce que "4" n'est pas un enregistrement de self[item].

    Personnellement, j'écrirais surement qq chose comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class classifier:
        def __init__():
            self.wx = {}
        def aug(self, item, kart):
            self.wx[item][kart] = self.wx.setdefault(item, {}).get(kart, 0)+1

Discussions similaires

  1. Réponses: 3
    Dernier message: 20/01/2011, 02h00
  2. [debutant] [servlets] methode init()
    Par be_on_edge dans le forum Servlets/JSP
    Réponses: 5
    Dernier message: 01/03/2004, 15h11
  3. [METHODE] -> Détection de virus ?
    Par MaTHieU_ dans le forum C++Builder
    Réponses: 2
    Dernier message: 11/02/2004, 17h04
  4. Passage de variable par methode post ?
    Par oazar dans le forum Flash
    Réponses: 33
    Dernier message: 16/10/2003, 17h03
  5. Methode de drcherche a l,interieur de basse de donner texte
    Par philippe V dans le forum Autres SGBD
    Réponses: 4
    Dernier message: 03/12/2002, 10h20

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