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 :

Problème avec l'utilisation d'une classe


Sujet :

Python

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    105
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 105
    Points : 67
    Points
    67
    Par défaut Problème avec l'utilisation d'une classe
    Bonjour à tous,

    Je croyais avoir compris ce qu'était une classe, comment ça fonctionne...
    Aujourd'hui je ré-essaye et crac !
    Bin, non !
    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
    import random
     
    class sommes(object):
        def __init__(self,fin):
            n=random.randint(3,fin)
            return n
     
        def test(self,i):
            n+=i
            if n%2==0:
                c.pair(n)
            else:
                c.impair(n)
            return
     
        def pair(self,n):
            print n,n*(n+1)/2
            return
     
        def impair(self,n):
            print n,n**2
            return
     
    c=sommes()
    for i in range(12):
        c.test(i)
    D'accord, c'est un truc bidon...
    Mais je voulais initialiser un nombre n, à l'intérieur de la classe, par un choix aléatoire entre 3 et 10 à la création d'une instance.
    Puis je voulais en boucle ajouter la valeur de i à ce nombre n, tester si le nouveau nombre est pair ou impair et, selon, afficher la bonne valeur de la somme soit des n premiers nombres entiers soit de la somme des n premiers pairs.

    Et j'ai ce message d'erreur
    Traceback (most recent call last):
    File "C:\Python26\essai_classe.py", line 24, in <module>
    c=sommes()
    TypeError: __init__() takes exactly 2 arguments (1 given)
    Et là, je suis dépassé : un truc tout bête à savoir, c'est sûr... mais que je ne sais pas !

    D'autre part,
    si j'appelle pair(n) et impair(n) au lieu de c.pair(n) et c.impair(n), j'ai aussi un message d'erreur :
    Traceback (most recent call last):
    File "C:\Python26\essai_classe.py", line 21, in <module>
    c.test(i)
    File "C:\Python26\essai_classe.py", line 8, in test
    impair(n)
    NameError: global name 'impair' is not defined
    Là encore, pourquoi ?

    Je commence à douter savoir écrire un jour une classe, même simple, sans erreur...
    Et tant que je ne sais pas faire ça, je ne progresserai pas en Python : j'ai uun seuil à franchir.
    M'enfin, je persiste quand même.

    Merci d'avance à l'âme charitable qui voudra bien prendre de son temps pour éclairer mon chemin...

    @+

  2. #2
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Points : 891
    Points
    891
    Par défaut
    bonjour, en effet ca ne va pas.

    Vous avez défini une classe avec une méthode __init__. Cette méthode est le constructeur et elle attend un paramètre.
    Mais quand vous y faites appel, vous ne passez aucun paramètre.
    Je vous conseille de relire le tuto de G SWINNEN.

    N'hésitez pas si vous avez d'autres question.

    PS : je pense que le return n dans le __init__ va aussi poser problème.

  3. #3
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Points : 891
    Points
    891
    Par défaut
    Je reviens pour complément.

    Il est normal d'avoir une erreur si vous appelez pair(n), ...

    En effet, je vais essayer de vous expliquer simplement le concept objet.

    prenez la classe interrupteur (oui,oui!)

    un interrupteur est un objet qui permet d'allumer ou éteindre un système électrique (lumière, ordinateur,...)

    cet objet a deux actions possible (des méthodes), éteindre et allumer.

    cet objet a un état de départ (une propriété), soit il est en position ON, soit en position OFF.

    si je met cet objet sous forme de classe, ça donnerait ceci.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class interrupteur:
        def __init__(self,etat):
            self.etat=etat
     
        def allumer(self):
            self.etat="ON"
            return "le circuit est fermé"
     
        def eteindre(self):
            self.etat="OFF"
            return "le circuit est ouvert"
    Maintenant, j'utilise mon objet

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    monInterrupteur=interrupteur(ON)
    monInterrupteur.eteindre()
    Quand on instancie une objet, il faut lui passer les paramétres suffisant pour qu'il soit correctement initialisé. Dans notre cas on désire connaitre son état de départ (les électricien surtout, ils ne veulent pas prendre de coup d'électricité, )

    vous comprenez bien que lorsque l'on utilise un objet, on appelle ses méthodes en le désignant, parce que sinon le programme ne sait pas ou est la méthode éteindre, et surtout sur quel objet il doit agir.

    J'espère que ce cours rapide vous aidera à avancer

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    105
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 105
    Points : 67
    Points
    67
    Par défaut
    Bonsoir,

    Et merci...
    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
    import random
     
    class sommes(object):
        def __init__(self,fin):
            self.n=random.randint(3,fin)
     
        def test(self):
            self.n+=1
            if self.n%2==0:
                c.pair(self.n)
            else:
                c.impair(self.n)
            return
     
        def pair(self,n):
            print n,n*(n+1)/2
            return
     
        def impair(self,n):
            print n,n**2
            return
     
    c=sommes(25)
    for i in range(12):
        c.test()
    Voilà, ça, ça fonctionne...
    Cela dit, je voudrais bien savoir :
    * pourquoi si je remplace les self.n par des n tout court un message d'erreur me dit que j'assigne la variable n avant de l'avoir déclarée,
    * pourquoi dans def pair et impair, je n'ai plus besoin d'écrire self.n et que n suffit
    * pourquoi dans le def test, appeler pair(self,n) au lieu de c.pair(n) déclenche une erreur disant que pair n'est pas défini...

    Je n'ai pas le temps ce soir de relire Swinnen, mais je vais le faire, mais si déjà j'avais ici une réponse à mes questions, la re-lecture de Swinnen apporterait deux éclairages au lieu d'un...

    Merci d'avance...

  5. #5
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Points : 891
    Points
    891
    Par défaut
    Alors, on va reprendre un petit peu. Vous comprenez bien que lorsque vous utilisez un objet, vous utilisez ses propriétés et méthodes. ce qu'il encapsule n'interagit pas directement avec le reste du programme.

    Ainsi, le mot self, défini l'objet lui même, cad l'instance que vous avez créé.
    quand vous souhaitez accéder a des méthodes ou propriété propre a l'objet a l'intérieur de l'objet, vous devez utiliser self pour dire au programme que ce que vous souhaitez utilisez est a l'intérieur de l'objet. Sinon si vous souhaitez utiliser depuis l'extérieur de l'objet, vous devez utilisez le nom de l'instance que vous avez créé (dans votre cas c'est c.)

    je corrige votre code :
    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
     
     
    import random
     
    class sommes(object):
        def __init__(self,fin):
            self.n=random.randint(3,fin)
     
        def test(self):
            self.n+=1
            if self.n%2==0:
                return self.pair()
            else:
                return self.impair()
     
     
        def pair(self):
            return self.n,self.n*(self.n+1)/2
     
     
        def impair(self):
            return self.n,self.n**2
     
     
    for i in range(4,25):
        c=sommes(i)
        print c.test()
    je pense que c'est plus cohérent, peut être pas ce que vous souhaitez obtenir mais c'est cohérent.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    105
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 105
    Points : 67
    Points
    67
    Par défaut
    Re,

    Ok, merci...
    J'avais posté sans avoir vu le "complément d'information" dont j'ai pris connaissance maintenant...
    Je vais méditer tout ça...
    En fait, j'ai écrit dans le temps, en Basic Amstrad CPC 6128, un programme de conjugaison incollable et autocorrectif à la demande.
    Codé comme un pied, pourtant, il fonctionnait vite et bien et déterminait en 5/6 lignes si un verbe en ir était du 2e ou 3e groupe (6 mois pour trouver l'astuce). Je l'avais bien plus tard, au prix de quelques "contorsions", traduit en Turbo-Basic.
    Là, je voudrais le passer en Python, mais je m'aperçois que si j'utilise des classes/groupes, j'aurai une programmation plus "confortable"...
    D'où mon retour sur les classes...

    Bon, bin, j'ai de quoi méditer...

    Merci encore.

    @+

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

    [EDIT] grillé par airod... Je pense toutefois que ma réponse apporte quelques détails supplémentaires.

    Citation Envoyé par yoshik Voir le message
    * pourquoi si je remplace les self.n par des n tout court un message d'erreur me dit que j'assigne la variable n avant de l'avoir déclarée,
    Parce que n et self.n sont deux variables distinctes. self.n est un attribut de l'objet. self.n sera disponible dans toute méthode de la classe, car self est passé comme argument à ces méthodes. n est une variable locale, mais elle n'existe pas si tu ne la crées pas dans la méthode (au moyen d'un assignation, ou en le passant comme argument).

    * pourquoi dans def pair et impair, je n'ai plus besoin d'écrire self.n et que n suffit
    cf le point précédent. Ici, tu passes n comme argument. Mais en fait ce n'est pas nécessaire. Je te conseillerais de ne pas passer n comme argument, et d'écrire ici aussi self.n au lieu de n.

    * pourquoi dans le def test, appeler pair(self,n) au lieu de c.pair(n) déclenche une erreur disant que pair n'est pas défini...
    pair est une méthode de la classe. Une méthode s'appelle sur un objet de cette classe. C'est à dire qu'il faut faire précéder le nom de la méthode par une objet de la classe pour qu'il sache où trouver la méthode pair. En effet, tu pourrais très bien avoir plusieurs classes différentes qui possèdent chacune une méthode pair. Mais utiliser c est une très mauvaise idée; cela passe car c est bien une instance de la classe, mais ça casse complètement l'encapsulation, vu que ta classe dépend d'une instance particulière qui est créée ensuite. Utiliser self.n dans le code de pair (comme suggéré au point précédent) ferait alors référence à c.n, c'est à dire à l'attribut n de l'objet c, et pas à l'attribut n de l'objet courant, si tu crées plusieurs objet. Ce qu'il faut écrire c'est self.pair(n).

  8. #8
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut Rectification dans la présentation (reste a faire en français....)
    Bonjour,

    Citation Envoyé par airod Voir le message
    Vous avez défini une classe avec une méthode __init__. Cette méthode est le constructeur
    Petites précisions sur cette phrase qui risque d'être acquise. A corriger si besoin.

    la méthode __init__() est la première appelée lors de l'instanciation d'une classe, son premier argument fait toujours référence à l'instance (celle de la méthode __init__) en cours. Par convention ce premier argument se nomme 'self'. Ce n'est donc pas un mot Python mais c'est tellement important qu'il est fortement conseillé de toujours utiliser le mots 'self'.
    Du fait que l'instance ne soit visible qu'après __init__(), comme il se comporte comme un constructeur (et y ressemble) on pourrais croire que c'est Le 'constructeur' de l'instance, il n'en est rien.
    L'instance existe avant puisque 'self' y fait référence.
    Mais qui construit l'instance alors ? Tout simplement ().
    Lorsque vous écrivez a=Foo() Python comprend qu'il doit créer une instance de Foo. Il vas ensuite lire la méthode __init__ si elle est présente, puis inscrit tout cela dans le dico (espace de nom) sous la forme 'a': <instance de Foo>.
    Bon, puisque c'était juste pour cette histoire de constructeur, et que je pense que vous avez compris grâce à dividee et airod l'utilité de 'self' pour la visibilité de votre variable, je ne vais pas aller plus loin.

    Trois choses à propos du code maintenant :

    Vous aurez compris l'inutilité du return tout cour a la fin d'une fonction/méthode : Une fonction/méthode sans return retourne toujours None.
    Je vois une différence entre votre code et celui d'airod : Vous ne créez qu'une instance alors qu'airod en crée une à chaque passage dans sa boucle for. Comme cela 'écrase' (pas très joli comme explication ça) la précédent dans l'espace de nom on ne vois rien. Dans le code présent pas de problème mais si un autre objet fait appel à une méthode de l'instance entre temps je vous laisse imaginer.
    Sauf si vous n'en avait pas besoin pour autre chose je ne vois pas l'utilité des méthodes pair et impair. En effet vous pouvez écrire directement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        def test(self):
            self.n += 1
            if self.n%2 == 0:
                return self.n, self.n*(self.n+1)/2
            else:
                return self.n, self.n**2
    @+

  9. #9
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    Mea culpa

    Citation Envoyé par PauseKawa Voir le message
    Je vois une différence entre votre code et celui d'airod : Vous ne créez qu'une instance alors qu'airod en crée une à chaque passage dans sa boucle for
    La boucle for c'est dans votre code juste avant.

  10. #10
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Points : 891
    Points
    891
    Par défaut
    je rebondis...

    je suis d'accord que l'exemple de code que j'ai corrigé n'est pas des plus propre, cependant le but était d'expliquer simplement le concept objet, et donner un résultat cohérent a partir du code initial, sans toutefois trop changer de facon a ce que notre ami puisse analyser, et faire un parallèle.



    Edit : J'ai été surpris d'apprendre que __init__ n'est pas le constructeur, donc j'ai fait une recherche et de mémoire je ne me suis pas trompé. Voir tuto G. SWINNEN. En effet, lorsque l'on crée une class, celle ci hérite implicitement d'une classe object. celle-ci implante des methodes de base, dont __init__. si __init__ n'est pas défini dans notre class, c'est celle du parent qui est appelée. (notion d'héritage)
    Par contre je demande ici, une affirmation de mes propos ou infirmation., je continu a fouiner pour vous trouver ou j'ai lu ca.....

  11. #11
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    Pas de quoi rebondir airod.

    Vos explications sont, je pense, plus que complètes pour yoshik et désolé pour lui d'aller plus loin. C'était juste pour cette histoire de 'constructeur'.
    A vrais dire j'ai passer la journée à me demander si j'apportais cette 'pseudo correction'.

    Notre 'fonction' dans nos réponses (lorsque on maitrise le sujet en question) n'est pas de donner du code tout cuit mais d'amener à la réflexion/compréhension il me semble.
    Ta réponse vas dans ce sens.

  12. #12
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Points : 891
    Points
    891
    Par défaut voici un petit test.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class MonObjet(object):
        def salut(self):
            return "salut"
     
     
    a=MonObjet()
    print a.salut()
    La primitive "object" existe bien, et apporte la structure d'un objet python.

    Je continu, je cherche encore ou j'ai lu ca! (non pas dans un but de défit, mais pour avoir la bonne info, ... )

  13. #13
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    Citation Envoyé par airod Voir le message
    Edit : J'ai été surpris d'apprendre que __init__ n'est pas le constructeur, donc j'ai fait une recherche et de mémoire je ne me suis pas trompé. Voir tuto G. SWINNEN. En effet, lorsque l'on crée une class, celle ci hérite implicitement d'une classe object. celle-ci implante des methodes de base, dont __init__. si __init__ n'est pas défini dans notre class, c'est celle du parent qui est appelée. (notion d'héritage)
    Oui __init__(): pass est implicite. Mais self n'existe pas dans ce cas.

  14. #14
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    Bien vu...

    Donc une classe hérite du mots 'self' ?
    il vas falloir retrouver tes sources svp.

  15. #15
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Points : 891
    Points
    891
    Par défaut
    je pense que par défaut le modèle object passe self a __init__.
    Si lorsque l'on crée une class, on ne redéfinit pas le nom self par autre chose dans un nouveau __init__, c'est bien self qui est passer dans notre nouvelle class. ainsi on peut ecrire une class sans __init__.
    Mais ça va plus loin, on n'est pas obligé de définir le même nom pour la classe elle même. Un exemple, complétement fou ....

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class a():
     
        def P(self,u):
            return u
        def V(a,x):
            return x
     
    a=a()
    print a.P(5)
    print a.V(8)
    c'est juste le mécanisme de python qui implicitement affecte au premier paramètre la référence a l'objet instancié. Ai je tord?

    A vrai dire le bout de code ci dessus me donne mal au crane. en voici un autre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class a():
     
        def P(self,u):
            self.u=u
        def V(a):
            return a.u
     
    a=a()
    a.P(5)
    print a.V()
    Qu'en penses tu?

  16. #16
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Points : 891
    Points
    891
    Par défaut
    Ca y est je pense avoir trouvé un début de réponse,
    En effet __init__ ne serait pas le constructeur, c'est seulement la méthode appelée après la construction de l'objet, si cette méthode existe dans l'objet ou un de ses parents.

    Créer une classe n'hérite apparemment pas de "object", car si l'on fait ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class A(object):
        pass
     
    a=A()
     
    print dir(a)
    on obtient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__']
    alors que si l'on fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class A:
        pass
     
    a=A()
     
    print dir(a)
    on obtient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ['__doc__', '__module__']
    on voit bien que l'on obtient pas la même chose.
    Mais alors d’où viennent __doc__, et __module__?



    Bon allez ! on va arrêter là car on va devenir marteau. je n'arrête pas de tomber sur des infos contradictoires.
    http://python.50webs.com/CHAP_7/chap_7.html
    voir en bas.


  17. #17
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Du fait que pour un grand nombre __init__ est le constructeur, il va falloir rester sur les docs officielles pour tirer cela au clair.
    Désolé yoshik, je pense que tu vas avoir une doc complète sur les classes.

    Voici ce que dit le tuto de python.org (9.3.2)

    Class objects support two kinds of operations: attribute references and instantiation.

    Attribute references use the standard syntax used for all attribute references in Python: obj.name. Valid attribute names are all the names that were in the class’s namespace when the class object was created. So, if the class definition looked like this:

    class MyClass:
    """A simple example class"""
    i = 12345
    def f(self):
    return 'hello world'

    then MyClass.i and MyClass.f are valid attribute references, returning an integer and a function object, respectively. Class attributes can also be assigned to, so you can change the value of MyClass.i by assignment. __doc__ is also a valid attribute, returning the docstring belonging to the class: "A simple example class".

    Class instantiation uses function notation. Just pretend that the class object is a parameterless function that returns a new instance of the class. For example (assuming the above class):

    x = MyClass()

    creates a new instance of the class and assigns this object to the local variable x.

    The instantiation operation (“calling” a class object) creates an empty object. Many classes like to create objects with instances customized to a specific initial state. Therefore a class may define a special method named __init__(), like this:

    def __init__(self):
    self.data = []

    When a class defines an __init__() method, class instantiation automatically invokes __init__() for the newly-created class instance. So in this example, a new, initialized instance can be obtained by:

    x = MyClass()


    Of course, the __init__() method may have arguments for greater flexibility. In that case, arguments given to the class instantiation operator are passed on to __init__(). For example,

    >>> class Complex:
    ... def __init__(self, realpart, imagpart):
    ... self.r = realpart
    ... self.i = imagpart
    ...
    >>> x = Complex(3.0, -4.5)
    >>> x.r, x.i
    (3.0, -4.5)
    Ce qui n'est pas loin de ce que je dis sur __init__() en tant que méthode de 'customisation'.

    (Attention : ce qui suit est a vérifier)
    Ce qui me défrise c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class MyClass:
        """A simple example class"""
        i = 12345
        def f(self):
            return 'hello world'
    Mais en y réfléchissant cela semble normal si on se dit que Python traduit monobjet.methode() par maclasse.methode(monobjet).
    Soit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class maclasse():
        def salut(monobjet):
            return "salut"
     
    a=maclasse()
    print a.salut()
    Pour ce qui est de __module__ c'est sans doute oser de dire que cela viens du constructeur (comprendre c'est une instance donc on rajoute __module__).
    Idem pour __doc__ ? J'ai déjà lu quelque pars qu'une classe devrait toujours avoir un docstring par convention.
    Je ne parle pas de class A(object) ou là c'est l'héritage.

    Il vas falloir trouver cela dans la doc...

    @+

  18. #18
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

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

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Points : 970
    Points
    970
    Par défaut
    bonjour,

    juste pour rebondir sur la discussion de airod et de PauseKawa, désoler de polluer ton post yoshik.

    __init__ n'est en effet pas le constructeur, ce rôle est dévolu à __new__.

    exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Toto(object):
        def __new__(cls, *args, **kwargs):
            print "__new__"
            return object.__new__(cls)
        def __init__(self, name):
            print "__init__"
            self._name = name
        def name(sefl):
            return self._name
    c'est object.__new__(cls) qui crée véritablement l'instance à partir de la classe.
    cls dans __new__ correspond à la classe elle même, pas à l'instance.

    Notez que __new__ n'appelle pas explicitement __init__. Cet enchainement d'appel est quant à lui dévolu à... la métaclasse de object, soit type. Mais c'est une autre histoire Pour faire simple, les classes sont des instances de métaclasses au même titre que les objets sont des instances de classe.

  19. #19
    Membre éprouvé

    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
    Points : 1 273
    Points
    1 273
    Par défaut
    Salut

    Quand on définit un classe comma ça :
    On définit une “vieille” classe, ce qui n ’est plus conseillé depuis beau temps… Les classes modernes doivent systématiquement dériver (directement ou indirectement) de object :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class A(object):
        pass
     
    class B(A):
        pass
    Et __init__ n’est en effet qu’une fonction d’initialisation, qui dispose déjà de l’instance de la classe (le fameux self). Le vrai constructeur, c’est __new__, assez peu utilisé (sauf dans le cas de meta-classes, comme dans Django ou le bpy de Blender, par exemple). Lui prend en premier paramètre non pas une instance de la classe, mais la classe elle-même (car c’est une méthode de classe…), et est censé retourner une instance de la classe, sur laquelle sera appelé __init__()…

    Et comme __new__ et __init__ sont également définis pour object, grâce à l’héritage, on n’est pas forcé de les définir si on n’en a pas besoin.

    [Edit] (Partiellement) grillé par kango !

    [Edit] Sources : la doc officielle

  20. #20
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Points : 891
    Points
    891
    Par défaut
    voilà que je suis d'accord avec vous, (tout mes livres sur le sujet étant a mon travail je n'ai pu vérifier que ce matin)

    en effet __init__ n'est pas le constructeur, mais l'initialisateur. Le constructeur etant bien __new__.

    Nous voilà tous d'accord.

    Hummm, j'aime bien les post comme ca!

    merci a tous.

    yoshik pour ne pas te predre dans le concept par rapport a ton problème de départ, ne prend pas en compte tout notre débat autour du constructeur, tu risque de te perdre.

    Qui se dévoue pour corriger G SWINNEN,....
    voir chapitre 12.2

    http://python.developpez.com/cours/TutoSwinnen/?page=Chapitre12

    Bon allez je blague !


Discussions similaires

  1. Réponses: 4
    Dernier message: 19/07/2009, 13h51
  2. Réponses: 7
    Dernier message: 27/01/2009, 08h25
  3. [POO] Problème avec un require_once dans une classe
    Par Sayrus dans le forum Langage
    Réponses: 5
    Dernier message: 23/02/2008, 14h40
  4. problème avec l'utilisation d'une fonction
    Par mcspawn dans le forum Langage
    Réponses: 6
    Dernier message: 06/06/2007, 15h39
  5. [Système] Problème avec les méthodes d'une classe
    Par oussama127 dans le forum Langage
    Réponses: 7
    Dernier message: 30/08/2006, 09h18

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