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 :

Dictionnaire : Changer l'index/clé


Sujet :

Python

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 12
    Par défaut Dictionnaire : Changer l'index/clé
    Bonjour,

    Tout d'abord je m'excuse si cette question est élémentaire, je débute en python et même si j'ai l'impression de progresser vite, je bute souvent sous des difficultés un peu débile
    (je viens du monde C )

    Je n'ai trouvé nul part comment on peut changer l'index (ou la clé) dans un dictionnaire...

    J'utilise le dictionnaire comme un tableau de pointeur où on peut affecter à chaque pointeur un label.

    Or, si je veux changer ce label, impossible...

    je suis obliger de créer une fonction qui insère le nouveau label et ensuite qui parcourt l'ancien label pour recopier les données.

    Je trouve cela super pénalisant, surtout si j'utilise le programme pour un dictionnaire à plusieurs milliers d'entrées...

    Je vous remercie !!

  2. #2
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    bonsoir,

    tu veux faire quelquechose comme ça ?:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    d = {}
    d[1] = "un"
    d[2] = "deux"
    d[10] = d[1]
    del d[1]
    la clé associée à "un" passe de 1 à 10 dans ce cas. ce n'est pas nécessaire de parcourir l'ensemble du dictionnaire sinon tu passes d'une méthode en O à une méthode en O(n)

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 12
    Par défaut
    Hmm, je vais essayer.

    Vous avez bien ciblé le problème de calculabilité que je cherche à éviter.

    Par contre, si je n'ai pas fait ce que vous proposez, c'est parce qu'il me semblait que des affectations par copie comme cela n'avaient pour but que de recopier le pointeur et non les valeurs.
    Donc, si je modifie le premier, le deuxième nouvellement créé pointant vers le même, va forcément être détruit également non ?

    Où est mon erreur ?

    Merci bien, je visualise (avec ce système, je vais faire des tests) comment optimiser mon code (en fait, j'ai un dictionnaire de dictionnaire)

    merci !!

  4. #4
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    la fonction id() permet de connaitre l'adresse mémoire (après une conversion en hexa).

    dans l'exemple que je te donne id(d[1] avant changement) = id(d[10 après changement) il n'y a pas de "recopie" de la valeur, c'est la même et au même emplacement mémoire.

    python utilise un compteur de référence. la chaine "un" est référencée 1 fois par d[1].

    dès que je fais d[10] = d[1], la chaine "un" est référencée 2 fois, une fois par d[1] et une fois par d[10].

    dès que je fais del d[1] elle n'est plus référencée que par d[10] donc la chaine ne part pas au ramasse miettes, pas de soucis.

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 12
    Par défaut
    dès que je fais del d[1] elle n'est plus référencée que par d[10] donc la chaine ne part pas au ramasse miettes, pas de soucis.
    Rho, génial !!

    je pensais pas que ca avait été prévu

    merci mille fois !!

    (et merci pour l'info du id(), je vais pouvoir m'en servir)

  6. #6
    Membre chevronné
    Avatar de vincent.mbg
    Homme Profil pro
    Développeur Python
    Inscrit en
    Décembre 2007
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Python

    Informations forums :
    Inscription : Décembre 2007
    Messages : 327
    Par défaut
    Bonjour,

    Tu parle souvent de pointeur est c'est une bonne façon de penser ceci dit il y a parfois des subtilités.
    En Python, on distingue les types immuables et les non-immuables. 1 étant un entier il est immuable.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    >>> a = 1
    >>> id( a )
    23447032
    >>> a += 1
    >>> id(a)
    23447008
    >>>
    Python ne modifie jamais un entier ou un string, il en recrée un

    Les listes par exemple sont non-immuables
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    >>> b = [1]
    >>> id( b )
    140205508242392
    >>> b += [2]
    >>> id( b )
    140205508242392
    >>>
    Un petit exemple surprenant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    >>> a = 1
    >>> b = 1
    >>> id( a )
    23447032
    >>> id( b )
    23447032
    >>>
    Python ne prend pas la peine de recréer un objet car de toute façon si a ou b est modifié il sera en réalité recréé.
    Mon guide pour apprendre Tkinter - N'oubliez pas de consulter les FAQ Python ou de visiter mon blog

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 12
    Par défaut
    Bonjour,

    Effectivement je parle souvent de pointeur car je viens du C et que j'ai une formation "bas niveau".
    Comme dit avec un ami qui a fait un cursus info, dans la vie, ya les gens de haut niveau et des gens de bas niveau (et moaa, jsuis en bas lol)

    Ou dit autrement, ya les softeux et les hardeurs (et moi, je fais du hard )

    Bref, j'ai une assez bonne connaissance de l'assembleur, du C et du VHDL, et j'ai décroché lorsque j'ai étudié Java et C++ (l'horreur des classes et de la POO)

    Je m'y mets de force, et j'ai choisi python (communauté, Inkscape, google, etc.). Début douloureux mais ca se passe assez bien maintenant, mais je débute toujours).

    Pour en revenir aux types immuables et non-immuables, je pense avoir compris.

    Python a du être fait pour que certaines types soient codés "en dur" pour un gain de performance (et pratique niveau compilateur).

    Ainsi, si je reprend votre exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    >>> a=1
    >>> id(a)
    505389048
    >>> id(1)
    505389048
    >>> id(2)
    505389064
    >>> a=2
    >>> id(a)
    505389064
    On voit que "a" ne fait que pointer sur l'emplacement à laquelle sa variable est "fixée". Une affectation n'est qu'un changement de pointeur.

    Les listes ne sont qu'une structure. Donc j'en déduis que les types entiers et les types caractères sont codés en dur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    >>> id(b)
    Traceback (most recent call last):
      File "<pyshell#6>", line 1, in <module>
        id(b)
    NameError: name 'b' is not defined
    >>> id('b')
    11807712
    >>> a='b'
    >>> id(a)
    11807712
    Ca en à l'air...
    Marrant tout de même, je me demande s'il y a une liste de tout ce qui est déjà codé, et la charge à l'ouverture du GUI (surtout si liste infinie). car même demander l'id() d'un entier à plein de chiffre renvoi une valeur...

  8. #8
    Membre chevronné
    Avatar de vincent.mbg
    Homme Profil pro
    Développeur Python
    Inscrit en
    Décembre 2007
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Python

    Informations forums :
    Inscription : Décembre 2007
    Messages : 327
    Par défaut
    Une affectation n'est qu'un changement de pointeur.
    Je dirais plutôt qu'une affectation crée un pointeur. Mais il ne faut pas voir ce type de pointeur comme celui du C qui donne accès directement à la mémoire. On ne peut pas utiliser la valeur de retour de id().

    Cette exemple est étrange.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    >>> id(2)
    505389064
    >>> a=2
    >>> id(a)
    505389064

    Je m'explique.
    En python chaque objet créé a un compteur de référence.
    Si je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    >>> 1
    1 # Compteur de référence à 0.
    un objet 1 est créer

    si je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    a = 1  # Compteur de référence à 1.
    b = c = a # Compteur de référence à 3.
    del a, b, c # Compteur de référence à 0
    Chaque objet créé à un compteur de référence, qui est incrémenté dés qu'il y a une affectation vers cette objet. Si ce compteur est à 0, la mémoire alloué pour cette objet est libérée.

    Pourquoi alors dans cette exemple l'adresse est-elle la même ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    >>> id(2)
    505389064 
    >>> a=2
    >>> id(a)
    505389064
    l'adresse est elle libérée puis récupéré ?
    Mon guide pour apprendre Tkinter - N'oubliez pas de consulter les FAQ Python ou de visiter mon blog

  9. #9
    Membre Expert Avatar de pacificator
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 074
    Par défaut
    Si ce compteur est à 0, la mémoire alloué pour cette objet est libérée.
    la memoire allouée pour cet objet est susceptible d'être liberée, à n'importe quel moment, en fonction de l'implémentation du GC.

  10. #10
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 746
    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 746
    Par défaut
    Pour "voir" le nombre de reférences:

    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    from sys import getrefcount
    print getrefcount(1)
    a = 1
    print getrefcount(1)
    a = 0
    print getrefcount(1)


    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> id(2)
    505389064    # l'adresse de 2
    >>> a=2      # a pointe vers l'objet 2
    >>> id(a)
    505389064    # ce que montre id(a) = id(2): les 
                         # identifiants du même objet "2"

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

  11. #11
    Membre chevronné
    Avatar de vincent.mbg
    Homme Profil pro
    Développeur Python
    Inscrit en
    Décembre 2007
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Python

    Informations forums :
    Inscription : Décembre 2007
    Messages : 327
    Par défaut
    Bonjour à vous deux et
    merci pour ces précisions

    Mais la je suis paumé !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    >>> a = 1
    >>> print getrefcount( a )
    299
    >>>
    Pourquoi le compteur de 1 commence à 299 ?
    Mon guide pour apprendre Tkinter - N'oubliez pas de consulter les FAQ Python ou de visiter mon blog

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 12
    Par défaut
    Hola,

    On déborde, mais comme c'est mon sujet, qu'il est déjà marqué comme résolu et donc ne gêne personne, je demande la clémence des modo pour le laisser un peu ouvert


    Heu, je vous avoue que vous m'avez un peu (voir complètement) perdu avec vos histoires de compteur de références....

  13. #13
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Par défaut
    Bonjour,

    Citation Envoyé par vincent.mbg Voir le message
    Bonjour à vous deux et
    merci pour ces précisions

    Mais la je suis paumé !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    >>> a = 1
    >>> print getrefcount( a )
    299
    >>>
    Pourquoi le compteur de 1 commence à 299 ?
    Il ne commence pas à 299, il est à 299 lorsque la commande getrefcount est appelée.
    Mais, auparavant, il y a plein de code Python qui a été exécuté.

    Par exemple, chez moi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    In [1]: import sys
     
    In [2]: sys.getrefcount(1)
    Out[2]: 1178
     
    In [3]: len(sys.modules)
    Out[3]: 322
    J'ai quand même 322 modules qui ont été chargés et dont le code a généré des références à des objets.
    Dès lors, il ne faut pas s'étonner du nombre élevé d'occurrences de certaines valeurs, qui plus est si elles sont susceptibles d'être utilisées fréquemment.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    In [49]: for i in xrange(-3, 4):
       ....:     print i, sys.getrefcount(i)
       ....:
       ....:
    -3 8
    -2 16
    -1 2589
    0 2150
    1 1168
    2 406
    3 163
    Pour le plaisir des neurones, il faut faire attention à getrefcount suivant que l'on est dans un shell Python ou quand on exécute du code, le résultat peut être différent (sans compter l'histoire des modules), à cause de la variable magique _ !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    >>> 1+2
    3
    >>> _
    3
    >>>
    Edit : Il faut savoir aussi que Python garde un cache des objets les + utilisés (petits entiers, petites chaines de caractère) et que ceux-là ne seront pas "garbage collectés".

    @badthings : désolé de persister dans la dérive, getrefcount indique en gros le nombre de pointeurs pointant sur une valeur, afin que le garbage collector puisse la supprimer lorsqu'elle n'est plus référencé (c'est ce qui évite de supprimer la valeur de ton d[10] après le del d[1]).
    Edit 2 : "Rendons à César, ..." cette explication est exactement celle de kango avec jute le terme getrefcount en + !

  14. #14
    Membre chevronné
    Avatar de vincent.mbg
    Homme Profil pro
    Développeur Python
    Inscrit en
    Décembre 2007
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Python

    Informations forums :
    Inscription : Décembre 2007
    Messages : 327
    Par défaut
    Merci pour cette explication

    La couche qui utilise 1 doit être très profonde je n'arrive pas a diminuer son compteur.
    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
     
    >>> import sys
    >>> sys.getrefcount(1)
    300
    >>> globals()
    {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'sys': <module 'sys' (built-in)>, '__doc__': None, '__package__': None}
    >>> alias = sys.getrefcount
    >>> globals().pop( "sys" )
    <module 'sys' (built-in)>
    >>> globals().pop( "__builtins__" )
    <module '__builtin__' (built-in)>
    >>> alias( 1 )
    300
    >>> globals()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'globals' is not defined
    Peu import c'était juste pour le plaisir de bidouiller des concept qui n'ont pas grande utilité à être manipulé lorsque l'on développe.
    Mon guide pour apprendre Tkinter - N'oubliez pas de consulter les FAQ Python ou de visiter mon blog

  15. #15
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Par défaut
    Citation Envoyé par vincent.mbg Voir le message
    [...]
    Peu import [...]
    C'est voulu, ce jeu de mot ?

  16. #16
    Membre chevronné
    Avatar de vincent.mbg
    Homme Profil pro
    Développeur Python
    Inscrit en
    Décembre 2007
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Python

    Informations forums :
    Inscription : Décembre 2007
    Messages : 327
    Par défaut
    Non désolé.
    mais il m'arrive également de mettre un ; avant d'aller à la ligne
    Mon guide pour apprendre Tkinter - N'oubliez pas de consulter les FAQ Python ou de visiter mon blog

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

Discussions similaires

  1. CHANGER UN INDEX DE TABLESPACE
    Par gallargues dans le forum Administration
    Réponses: 2
    Dernier message: 09/04/2010, 10h45
  2. evenement changer d'index
    Par zandru dans le forum Macros et VBA Excel
    Réponses: 14
    Dernier message: 02/07/2008, 16h12
  3. Changer les index de controles insérés dynamiquement
    Par BM42 dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 24/10/2007, 14h49
  4. Dictionnaire de type index
    Par mmooaa dans le forum Langages de programmation
    Réponses: 2
    Dernier message: 21/05/2007, 21h35
  5. changer le index.htm
    Par pharaonline dans le forum Apache
    Réponses: 2
    Dernier message: 16/06/2006, 20h13

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