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 :

POO Python, instanciation multiple ?


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 33
    Par défaut POO Python, instanciation multiple ?
    Bonjour à tous,

    Dans le cadre du boulot, j'essaye de me simplifier la vie en codant une map du reseau interne selon des données déjà collectées et présentes dans une base MySQL.
    J'essaye d'utiliser python en mode Objet (il faut bien commencer un jour), mais je me retrouve bloqué par des choses que je soupçonnes être basiques mais qui me bloque complêtement.

    En gros et pour faire simple, je cherche a avoir un objet Host qui va contenir une liste d'objet Interface qui vont elles même contenir chacune une liste de Gifs.

    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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
     
    import MySQLdb
     
    class Host:
     
            def __init__(self, nom, type="", interfaces=[]):
                    self.nom = nom
                    self.type = type
                    self.interfaces = interfaces
                    self.populateInts()
     
            def populateInts(self):
                    req="select nomInt, ipInt, maskInt from Interface where nomHost = '"+self.nom+"'"
                    connection = MySQLdb.connect(host=servername, user=username, passwd=password, db=dbname, port=port)
                    c = connection.cursor()
                    intList = c.execute(req)
                    intList = c.fetchall()
                    ## TENTATIVE DE DEBUG ##
                    print
                    print self.nom
                    print intList
                    print
                    print
                    ###########################
                    for int in intList:
                            self.interfaces.append(Interface(int[0], int[1], int[2], self.nom))
                    c.close()
                    connection.close()
     
     
    class Interface:
     
            def __init__(self, nom, ip='0.0.0.0', mask='0.0.0.0', host="", gifs=[]):
                    self.nom = nom
                    self.ip = ip
                    self.mask = mask
                    self.host = host
                    self.gifs = gifs
                    self.populateGifs()
     
            def populateGifs(self):
                    req="select nomGif, hostSrcIp, ipSrc, hostDest, hostDestIp, ipDest, etatGif, costGif, maskGif from Gif where nomInt = '"+self.nom+"' and nomHost = '"+self.host+"'"
                    connection = MySQLdb.connect(host=servername, user=username, passwd=password, db=dbname, port=port)
                    c = connection.cursor()
                    gifList = c.execute(req)
                    gifList = c.fetchall()
                    for gif in gifList:
                            self.gifs.append(Gif(gif[0], gif[1], gif[2], gif[3], gif[4], gif[5], gif[6], gif[7], gif[8], self.host, self.nom))
                    c.close()
                    connection.close()
     
     
    class Gif:
     
            def __init__(self, nom, hostSrcIp='0.0.0.0', ipSrc='0.0.0.0', hostDest="", hostDestIp='0.0.0.0', ipDest='0.0.0.0', etat='', cost='', mask='', host="", int=""):
                    self.nom = nom
                    self.hostSrcIp = hostSrcIp
                    self.ipSrc = ipSrc
                    self.hostDest = hostDest
                    self.hostDestIp = hostDestIp
                    self.ipDest = ipDest
                    self.etat = etat
                    self.cost = cost
                    self.mask = mask
                    self.host = host
                    self.int = int
     
    h = Host('router1')
    h2 = Host('router2')
     
    ## TENTATIVE DE DEBUG ##
    print h.nom
    print len(h.interfaces)
    for i in h.interfaces:
            print "\t"+i.nom+" => "+str(len(i.gifs))
    print h2.nom
    print len(h2.interfaces)
    for i in h2.interfaces:
            print "\t"+i.nom+" => "+str(len(i.gifs))
    ##########################
    Cela me donne ceci :
    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
     
     
    ## ici ce sont les resultats printés dans la methode populateInts, on y voit des interfaces bien differentes :
    router1
    (('lo0', 'XX.XX.XX.XX', ''), ('enc0', '', ''), ('pflog0', '', ''), ('fxp1', 'XX.XX.XX.XX', '0xfffffff8'), ('fxp0', 'XX.XX.XX.XX', '0xffffff00'), ('fxp3', 'XX.XX.XX.XX', '0xfffffff8'), ('fxp4', 'XX.XX.XX.XX', '0xfffffff8'), ('fxp2', 'XX.XX.XX.XX', '0xfffffff8'), ('fxp5', 'XX.XX.XX.XX', '0xffffff00'), ('pfsync0', '', ''))
     
    gwbld3
    (('lo0', '127.0.0.1', ''), ('enc0', '', ''), ('pflog0', '', ''), ('fxp1', '', ''), ('fxp3', '', ''), ('fxp0', 'XX.XX.XX.XX', '0xffffff00'), ('fxp2', 'XXX.XXX.XXX.XXX', '0xfffffff8'), ('fxp5', '', ''), ('fxp4', '', ''), ('pfsync0', '', ''))
     
    ## ici ce qui est printé en fin de programme, on dirait que la liste self.interfaces est commune à mes deux instances :
     
    gwbld2
    20
            lo0 => 35
            enc0 => 35
            pflog0 => 35
            fxp1 => 35
            fxp0 => 35
            fxp3 => 35
            fxp4 => 35
            fxp2 => 35
            fxp5 => 35
            pfsync0 => 35
            lo0 => 35
            enc0 => 35
            pflog0 => 35
            fxp1 => 35
            fxp3 => 35
            fxp0 => 35
            fxp2 => 35
            fxp5 => 35
            fxp4 => 35
            pfsync0 => 35
    gwbld3
    20
            lo0 => 35
            enc0 => 35
            pflog0 => 35
            fxp1 => 35
            fxp0 => 35
            fxp3 => 35
            fxp4 => 35
            fxp2 => 35
            fxp5 => 35
            pfsync0 => 35
            lo0 => 35
            enc0 => 35
            pflog0 => 35
            fxp1 => 35
            fxp3 => 35
            fxp0 => 35
            fxp2 => 35
            fxp5 => 35
            fxp4 => 35
            pfsync0 => 35

    On dirait que ma liste d'interfaces est commune aux 2 Host.
    Et que la liste de gifs est commune à tous les objets Interface.

    Quelqu'un saurait-il me dire si mon raisonnement est bon, et du coup ce qui ne va pas dans ma façon de faire.
    Car les attributs de type string sont uniques à chaque instance mais par contre mes listes ne le sont pas, Pourquoi donc ?


    Merci à toi, qui à pris le temps de lire et peu-être même le temps de répondre

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 33
    Par défaut
    Ca fait une bonne heure que je galère et je viens de trouver d'où venait le problème, seulement je ne le comprends pas.

    Au lieu de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class Host:
     
        def __init__(self, nom, list=[])
            self.nom = nom
            self.list=list
    J'ai mis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class Host:
     
        def __init__(self, nom)
            self.nom = nom
            self.list=[]

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

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 068
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class Host:
        def __init__(self, nom, type="", interfaces=None):
            if not  interfaces:  interfaces = []
    si tu mets def __init__(self, nom, type="", interfaces=[]) python évalue interfaces une seule fois et les autres instantiations pointeront sur la même valeur ... en gros.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 33
    Par défaut
    Hum, donc si je comprends bien, un string vide peut être initialisé, mais une liste vide doit être considéré comme un objet quelconque.

    Fonctionnement plutôt étrange je trouve, mais ok je vais m'en contenter (pas vraiment le choix ).

    Et bien merci à toi (encore) pour l'explication.

    Problème résolu.

    PS : à ce soir si j'ai une nouvelle question sur PyGame, je compte continuer mon morpion pour passer ensuite à quelque chose du genre soit Casse-Brique soit Tetris.

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

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 068
    Par défaut
    Citation Envoyé par Ziranium Voir le message
    Hum, donc si je comprends bien, un string vide peut être initialisé, mais une liste vide doit être considéré comme un objet quelconque.

    Fonctionnement plutôt étrange je trouve, mais ok je vais m'en contenter (pas vraiment le choix ).
    un string n'est pas mutable ...

  6. #6
    Membre Expert

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Par défaut
    Dans Python, les strings, tous comme les int, float et autres types “de base”, sont immutables (ils ne peuvent pas changer de valeur – quand on assigne une chaîne à une variable existante, on crée en fait un nouvel objet string, on ne modifie pas l’existant), et donc toujours copiés par valeur, alors que les autres objets (dont les listes, dicts, etc.) sont copiés par références – un p’tit exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    str1 = "test"
    str2 = str1
    str2 += " nr 2"
    print(str1) # donne "test"
    print(str2) # donne "test nr 2"
    # Modifier str2 n’a pas affecté str1…
     
    l1 = [1, 2, 3]
    l2 = l1
    l2 += [4, 5, 6]
    print(l1) # donne [1, 2, 3, 4, 5, 6]
    print(l2) # donne [1, 2, 3, 4, 5, 6]
    # Les modifications sur l2 se sont répercutées sur l1…
    Autrement dit, la copie d’une string (ou int, float, etc.) donne toujours un nouvel objet, alors que la copie d’une liste (ou d’un dict, ou n’importe quel objet évolué) est “shallow”, c’est le même objet qui est assigné à la copie…

    D’où la vicieuse subtilité qui t’a posé problème : l’expression d’initialisation par défaut des variables d’une fonction est évaluée une seule fois, lors de la construction de cette fonction par le parseur, et les valeurs ainsi obtenues sont copiées à chaque appel de cette fonction, si nécessaire – donc, tu te retrouve toujours avec la même liste ! Oui, c’est vraiment vicieux, et bravo pour avoir trouvé une solution tout seul

    PS : j’espère que j’ai été clair, c’est pas un truc évident à expliquer, ni à comprendre…

    [edit] grillé par josmiley…

  7. #7
    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
    Bonsoir,

    Et la doc (4.7.1. Default Argument Values) qui vas avec.

    @+

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 33
    Par défaut
    Merci mont29 pour ton explication qui m'a bien permis de comprendre un truc en plus :

    l1 = [1, 2, 3]
    l2 = l1
    l2 += [4, 5, 6]
    print(l1) # donne [1, 2, 3, 4, 5, 6]
    print(l2) # donne [1, 2, 3, 4, 5, 6]
    # Les modifications sur l2 se sont répercutées sur l1…
    J'avoue avoir testé quand même ...

    Et aussi que le += équivaut à append, je ne savais pas.

    Merci également à toi PauseKawa pour le coté officiel.

    Avec tous ces éléments, impossible de retomber de nouveau sur ce type de soucis !

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

Discussions similaires

  1. Réponses: 8
    Dernier message: 09/09/2008, 16h19
  2. Problème d'instanciation multiples
    Par teddyalbina dans le forum C++/CLI
    Réponses: 5
    Dernier message: 04/07/2008, 18h14
  3. Réponses: 33
    Dernier message: 07/02/2008, 10h43
  4. Réponses: 2
    Dernier message: 14/09/2007, 08h55
  5. [Choix de langage] POO pour de multiples applications
    Par Shadowritter dans le forum Langages de programmation
    Réponses: 15
    Dernier message: 17/01/2005, 15h42

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