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 :

effet de bord avec "if __name__ == '__main__'" sur les (noms de) classes


Sujet :

Python

  1. #1
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut effet de bord avec "if __name__ == '__main__'" sur les (noms de) classes
    Pour tester les modules que j'écris, il m'arrive souvent d'écrire un bout de code supplémentaire à des fins de test (le classique "if __name__ == '__main__' ... " qui a le bon goût de n'être exécuté que quand on appelle directement le module et non pas quand on l'importe)

    Sauf que !

    Si cette partie de code suit une déclaration/définition de classe, un test avec 'isinstance' sur un objet de la dite-classe dans un autre module ne fonctionne plus car la classe est alors reconnue comme '__main__.nom_de_la_classe' et non plus comme 'nom_du_module.nom_de_la_classe'

    Exemple :

    dans classe_1.py
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    import classe_2
     
    class Classe_1(object):
     
        def __init__(self,nom):
            self.nom = nom
     
    if __name__ == "__main__":
        obj1 = Classe_1('un')
        obj2 = classe_2.Classe_2('deux',obj1)
    dans classe_2.py
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    import classe_1
     
    class Classe_2(object):
     
        def __init__(self,nom,obj_classe_1):
     
            assert isinstance(obj_classe_1,classe_1.Classe_1), type(obj_classe_1)        
            self.nom           = nom
            self.lien_classe_1 = obj_classe_1
    En interactif, tout se passe bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    ~ $ python
    Python 2.5.2 (r252:60911, Feb 22 2008, 07:57:53) 
    [GCC 4.0.1 (Apple Computer, Inc. build 5363)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import classe_1
    >>> import classe_2
    >>> obj1 = classe_1.Classe_1('un')
    >>> obj2 = classe_2.Classe_2('deux',obj1)
    >>> type(obj1)
    <class 'classe_1.Classe_1'>
    Mais si j'exécute directement classe_1.py :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    ~ $ python classe_1.py
    Traceback (most recent call last):
      File "classe_1.py", line 10, in <module>
        obj2 = classe_2.Classe_2('objet_2',obj1)
      File "/Users/pascal/classe_2.py", line 6, in __init__
        assert isinstance(obj_classe_1,classe_1.Classe_1), type(obj_classe_1)        
    AssertionError: <class '__main__.Classe_1'>
    ~ $
    Ce n'est évidemment pas un bug mais au moins un cas un peu particulier qui fait qu'un code correct s'avère "défaillant" quand on le teste de cette façon !
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  2. #2
    Membre éprouvé

    Profil pro
    Inscrit en
    Août 2004
    Messages
    723
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 723
    Points : 923
    Points
    923
    Par défaut
    A mon avis, il y a de grande chances que ça vienne de la façon dont Python gère les imports circulaires (d'ailleurs, ce genre de pratique est déconseillée...), qui exécute classe_1.py, donc obj1 est de type __main__.Classe_1, et du fait de l'import circulaire, en important classe_2.py, il réimporte classe_1.py, et ne fait pas le lien entre __main__.Classe_1 et classe_1.Classe_1, qui sont donc 2 types différents !

  3. #3
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Merci pour les commentaires et explications. L'import croisé/circulaire de deux classes et l'ordre des imports semblent bien être la cause du "problème" évoqué.

    Concernant ces imports circulaires déconseillés, je n'arrive pas à "sentir" les problèmes qui pourraient survenir (je suis peut-être mal placé pour dire ça, je viens d'en trouver un, par hasard ...). Après tout, les imports ne sont jamais que des imports d'espaces de noms.

    Dans certains domaines, dont le mien, les objets de classes différentes ont de nombreuses interactions entre eux et je ne vois pas trop comment éviter ces imports circulaires, si ce n'est de tout mettre dans le même module ... mais je n'ose l'imaginer.
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  4. #4
    Membre éprouvé

    Profil pro
    Inscrit en
    Août 2004
    Messages
    723
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 723
    Points : 923
    Points
    923
    Par défaut
    Comme solution, tu peux passer Classe_2 à une fonction définie dans classe_1.py (ou dans l'autre sens), qui en fera une variable globale.
    Sinon, il est possible d'utiliser un système d'"événements", soit avec une classe qui gère une file d'événements et agit en conséquence, soit avec un système "slot-signal", sur le même principe que le précédent mais de façon décentralisée, chaque classe interagit avec les autres, il suffit de passer des références aux constructeurs.

  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
    Une autre solution potentielle: on n'est pas obligé de faire l'import au niveau global; tu peux le faire à l'endroit où tu en as réellement besoin. Par exemple, si tu n'en as besoin que dans les test, tu peux le faire dans le "if __name__ == '__main__':". Ou à l'intérieur d'une fonction ou d'une méthode. Dans ce cas, les import circulaires ne devraient plus être un problème.

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

Discussions similaires

  1. [WebI XiR2] Graphique camembert avec des variables et un calcul sur les variables
    Par colom dans le forum Débuter
    Réponses: 0
    Dernier message: 12/02/2014, 14h02
  2. effet de bord avec les commentaires //
    Par awalter1 dans le forum Langage
    Réponses: 5
    Dernier message: 10/04/2012, 08h57
  3. Réponses: 3
    Dernier message: 23/08/2011, 11h53
  4. Question sur les tableaux avec en-têtes fixes et tri sur les colonnes
    Par lolo5935 dans le forum Général JavaScript
    Réponses: 14
    Dernier message: 29/07/2010, 15h50
  5. [DOM] Problème d'accent sur les noms de fichier avec mon parseur
    Par ujoodha dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 06/04/2006, 21h55

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