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 :

Références croisées dans les classes


Sujet :

Python

  1. #1
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut Références croisées dans les classes
    Bonjour

    J'ai un problème avec une classe X qui fait référence à une classe Y et une classe Y qui fait référence à une classe X. Et je n'arrive pas à trouver la bonne syntaxe pour que ça marche (comme une espèce de déclaration avant création comme en C)

    Exemple
    fichier "toto.py"
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
     
    from titi import *
     
    class toto:
    	def __init__(self):
    		self.other=titi

    fichier "titi.py"
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
     
    from toto import *
     
    class titi:
    	def __init__(self):
    		self.other=toto

    fichier "main.py"
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
     
    from toto import *
    from titi import *
     
    a=toto()
    b=titi()

    Bien évidemment ca plante (il me dit qu'il ne connait pas toto et si j'inverse les deux import alors c'est titi qui n'est plus connu). Je pensais pourtant qu'en ne mettant pas de parenthèses dans "other=toto" cela ne créait pas d'instance de classe mais stockait dans other seulement une référence vers la classe et que l'instance serait créée au moment ou j'appellerais a.other()

    Est-ce qu'il y a une solution à mon problème ???

    Merci à tous.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    La construction de la classe se fait "à l'import" alors que l'évaluation de la méthode __init__ ne se fera qu'à l'instanciation de la classe.
    Normalement, çà ne pose aucun problème.

    Dans votre cas ou plutôt qu'utiliser "import" vous avez fait des 'from...import'...

    Dans ce cas, on devra charger dans le globals() des contenus qu'on ne sait pas encore évaluer plutôt que des références a des contenus qui pourront être construits plus tard...

    une classe X qui fait référence à une classe Y et une classe Y qui fait référence à une classe X.
    Une classe n'étant pas une instance, l'exemple donné n'indique pas trop le cas d'utilisation que vous voulez réaliser.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut,

    La construction de la classe se fait "à l'import" alors que l'évaluation de la méthode __init__ ne se fera qu'à l'instanciation de la classe.
    C'est exactement ce que je croyais.

    Citation Envoyé par wiztricks Voir le message
    Normalement, çà ne pose aucun problème.
    Ben manifestement ça en pose...

    J'ai rajouté des print pour mieux voir ce qui se passe
    toto.py
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
     
    print "début toto"
    from titi import *
    class toto:
    	def __init__(self):
    		other=titi
     
    print "fin toto"

    titi.py
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
     
    print "début titi"
    from toto import *
    class titi:
    	def __init__(self):
    		other=toto
     
    print "fin titi"

    Appel de main
    début toto
    début titi
    fin titi
    fin toto
    Traceback (most recent call last):
    File "./main.py", line 8, in <module>
    b=titi()
    File "/home/moi/test/titi.py", line 8, in __init__
    other=toto
    NameError: global name 'toto' is not defined
    Donc les import se font bien. C'est quand j'instancie titi qu'il cherche à trouver la classe toto...

    Citation Envoyé par wiztricks Voir le message
    Dans votre cas ou plutôt qu'utiliser "import" vous avez fait des 'from...import'...
    Hum... je ne pensais pas que cela changeait quelque chose...

    Citation Envoyé par wiztricks Voir le message
    Dans ce cas, on devra charger dans le globals() des contenus qu'on ne sait pas encore évaluer plutôt que des références a des contenus qui pourront être construits plus tard...
    Je suis encore novice. Comment pourrait-on faire cela ???

    Citation Envoyé par wiztricks Voir le message
    Une classe n'étant pas une instance, l'exemple donné n'indique pas trop le cas d'utilisation que vous voulez réaliser.
    L'exemple donné est bien entendu un exemple minimaliste. En fait c'est dans un projet utilisant Qt et une bdd pour gérer une bibliothèque. Je crée un objet dérivé de QWidget permettant de remplir la table "livres". Cette table "livres" est liée à une table "auteurs". Je mets donc dans mon objet QLivre un bouton où quand on clique ça crée puis ouvre en sous-fenêtre l'objet QAuteur permettant de remplir la table "auteurs". Et de même cet objet QAuteur possède un bouton analogue permettant de créer et ouvrir l'objet QLivre qui permettra de remplir la table "livres". Ainsi l'utilisateur qui remplit "livres" peut, s'il manque l'auteur d'un livre, ouvrir en sous-fenêtre la boite "auteurs" pour remplir ce qui faut. Et inversement s'il commence par "auteurs" il peut d'un simple clic lui rajouter un livre...
    Et un paramètre embarquant la profondeur courante empêche de d'empiler les appels (livre->auteur->livre->auteur->...) à l'infini...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut

    Hum... je ne pensais pas que cela changeait quelque chose...
    Si penser vous empêche d'essayer...

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

  5. #5
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Bonsoir,

    le problème vient du fait que "from ... import ..." copie le contenu du module donné dans le namespace courant, au moment de l'import. Par contre avec "import ...", il crée une référence au module, c'est donc plus dynamique: si le contenu du module importé change, l'importateur verra les modifications.

    Avec le code donné, main importe toto, qui lui importe titi, mais à ce moment-là, le namespace du module toto est encore vide vu qu'il en est à la ligne où il importe titi, donc le "from toto import *" dans titi.py n'importe rien...

    Une autre solution (mais moins propre que d'utiliser "import ...") serait de déplacer le "from titi import *" à la fin de toto.py, après la création de la classe. Dans ce cas, il vaudrait mieux faire la même chose dans titi.py, pour ne pas dépendre de l'ordre des import. Je ne conseille pas cette solution, c'est juste pour illustrer le mécanisme...

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Si penser vous empêche d'essayer...
    Bien dit. Je l'envoie assez souvent aux autres pour pouvoir m'en prendre une quand je le mérite
    Parce que je viens effectivement de tester... et effectivement ça fonctionne

    toto.py
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
     
    import titi
    class toto:
    	def __init__(self):
    		self.other=titi.titi

    titi.py
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
     
    import toto
    class titi:
    	def __init__(self):
    		self.other=toto.toto

    main.py
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
     
    from toto import toto
    from titi import titi
     
    a=toto()
    print a, a.other, a.other()
     
    b=titi()
    print b, b.other, b.other()

    Mais je ne comprends pas pourquoi ça ne fonctionnait pas avant. Ni pourquoi ça ne fonctionne pas dans le cas suivant
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
     
    from toto import *
    from titi import *
     
    a=toto()
    print a, a.other, a.other()
     
    b=titi()
    print b, b.other, b.other()
    ...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    As-tu vu mon post ? Cela explique pourquoi cela ne fonctionnait pas avant.

    La raison pour laquelle le dernier code ne fonctionne pas et qu'il existe 2 toto: un module appelé toto et une classe appellée toto. Le module titi contient une référence au module toto (titi.toto), donc le "from titi import *" écrase la classe toto précédemment importée dans le main.py par la référence au module...

    La convention est de capitaliser (CamelCase) le nom des classes en Python, le module s’appellerait toto et la classe Toto.

  8. #8
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Erreur classique en Python que chacun de nous a dû faire un jour ou l'autre...

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dividee Voir le message
    As-tu vu mon post ? Cela explique pourquoi cela ne fonctionnait pas avant.
    Bonjour

    Non, désolé, quand j'ai commencé à taper ton post n'avait pas été "posté". Depuis je l'ai lu et j'ai mieux compris.

    Désolé aussi du retard à revenir conclure, j'étais un peu surbooké cette semaine. Donc effectivement grâce à cette nouvelle façon d'importer les modules tout mon projet se comporte nickel. Mon module "auteur" appelle le module "livres" qui, lui-même, peut rappeler une autre instance de "auteur" qui elle-même peut rappeler une autre instance de "livre" et etc etc (jusqu'à ce que la profondeur max des sous-fenêtres soit atteinte).

    Merci de vos aides
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

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

Discussions similaires

  1. les références dans les classes
    Par meryDev dans le forum Débuter
    Réponses: 4
    Dernier message: 24/01/2011, 22h51
  2. SDL dans les classes
    Par thekaz dans le forum Développement 2D, 3D et Jeux
    Réponses: 4
    Dernier message: 13/10/2006, 21h04
  3. fopen dans les classes
    Par poussinphp dans le forum C++
    Réponses: 5
    Dernier message: 06/07/2006, 01h08
  4. [C++] Pb avec les variable static dans les classe
    Par quantik-revolution dans le forum C++
    Réponses: 3
    Dernier message: 03/03/2006, 18h40
  5. [preferences] pouvoir débuguer dans les classes de JAVA
    Par Satch dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 25/01/2006, 13h23

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