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 :

self et Python


Sujet :

Python

  1. #1
    Candidat au Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Mai 2022
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Mai 2022
    Messages : 3
    Points : 2
    Points
    2
    Par défaut self et Python
    Bonjour,

    Je débute en python et j'ai du mal avec self.

    J'ai un fichier main.py qui instancie la classe Marche qui va chercher des fonctions dans un fichier initialisation.py
    Problème : python me dit qu'il ne connaît pas "valider_ajout_premiere_entite" qui est dans le fichier initialisation.py

    main.py
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/usr/bin/env python3.9
    """
    Fonction main
    """
     
    import marche
     
    if __name__ == "__main__":
        walk = marche.Marche()
        walk.title("marche")
        walk.mainloop()
    initialisation.py
    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
    import tkinter
    import tkinter.ttk
     
    class Initialisation(tkinter.Tk):
        def init(self):
     
            # caracteristique de la fenetre principale
            self.initialisation = tkinter.Toplevel()
            self.initialisation.geometry("400x200")
            self.initialisation.resizable(width=False, height=False)
     
            self.initialisation.lTitre = tkinter.ttk.Label(self.initialisation, text="Aucune entit├® n'est enregistr├®e, il en faut au moins une.", font='bold')
            self.initialisation.lEntite = tkinter.ttk.Label(self.initialisation, text="Quel est le nom de l'entit├® :")
            self.initialisation.eEntite = tkinter.ttk.Entry(self.initialisation)
            self.initialisation.lDistance = tkinter.ttk.Label(self.initialisation, text="Quelle est la distance parcourue :")
            self.initialisation.sDistance_Entite = tkinter.ttk.Spinbox(self.initialisation, from_=0.0, to=50.0, increment=0.1, width=5)
     
            self.initialisation.bValider = tkinter.ttk.Button(self.initialisation, text="Valider", command=self.initialisation.valider_ajout_premiere_entite)
     
            self.initialisation.lTitre.place(x=10, y=10)
            self.initialisation.lEntite.place(x=10, y=40)
            self.initialisation.eEntite.place(x=10, y=60)
            self.initialisation.lDistance.place(x=10, y=100)
            self.initialisation.sDistance_Entite.place(x=10, y=120)
            self.initialisation.bValider.place(x=10, y=160)
     
        def valider_ajout_premiere_entite(self):
            if self.eEntite.get() == "" or self.sDistance_Entite.get() == "":
                tkinter.messagebox.showerror("Erreur", "Une des 2 valeurs n'a pas ├®t├® correctement renseign├®es")
            else:
                chemin_distance = os.path.join(os.path.dirname(__file__), "distance")
     
                # on ajoute la premiere valeur au fichier distance
                with open(chemin_distance, "w") as data:
                    data.write(f"{entite} {self.initialisation.sDistance_Entite.get()}\n")
     
                self.initialisation.destroy()
    marche.py
    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 tkinter.ttk
    import tkinter
    import tkinter.messagebox
    import datetime
    import os
     
    import initialisation
     
    class Marche(tkinter.Tk):
        def __init__(self):
            tkinter.Tk.__init__(self)
     
            nom_entite, distance_entite = importation_entite()
     
            if len(nom_entite) == 0:
                initialisation.Initialisation.init(self)
     
    def importation_entite():
        nom_entite = ""
        distance_entite = ""
        chemin_distance = os.path.join(os.path.dirname(__file__), "distance")
        with open(chemin_distance, "r") as distance:
            for dist in distance:
                nom_entite += dist.split()[0] + " :\n"
                distance_entite += dist.split()[1] +" km\n"
        return nom_entite, distance_entite
    Pourriez-vous m'expliquer ce que je fais mal afin de progresser ?

    Merci

  2. #2
    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
    Bonjour
    Citation Envoyé par olivbarb59 Voir le message
    Je débute en python et j'ai du mal avec self

    J'ai un fichier main.py qui instancie la classe Marche qui va chercher des fonctions dans un fichier initialisation.py
    Problème : python me dit qu'il ne connaît pas "valider_ajout_premiere_entite" qui est dans le fichier initialisation.py
    Ca n'a rien à voir avec self.
    Ligne 8 tu écris self.initialisation = tkinter.Toplevel(). Ce qui signifie que dans l'instance de l'objet "Initialisation" tu crées un attribut "initialisation" (bon déjà avec ces noms trouvés avec tant d'originalité...)
    Cet attribut est de type "topLevel" de tkinter.
    Ligne 18 tu demandes à récupérer self.initialisation.valider_ajout_premiere_entite c'est à dire la méthode "valider_ajout_premiere_entite" de "self.initialisation" qui est donc un tkinter.topLevel. Or même si cet objet "tkinter.topLevel" possédait une méthode "valider_ajout_premiere_entite", celle-ci n'aurait absolument rien à voir avec la méthode "valider_ajout_premiere_entite" de ton objet "Initialisation". Mais elle n'en possède pas et c'est ce que te dit Python

    Citation Envoyé par olivbarb59 Voir le message
    Pourriez-vous m'expliquer ce que je fais mal afin de progresser ?
    Déjà tu n'as pas lu le message d'erreur qui t'explique lui-aussi tout ça. Il te dit qu'un tkinter.topLevel n'a pas d'attrbut "valider_ajout_premiere_entite" donc on ne peut pas faire plus clair, charge au codeur de comprendre pourquoi Python cherche "valider_ajout_premiere_entite" dans un tkinter.topLevel alors qu'il pensait le faire chercher dans un Initialisation (et on revient sur cette histoire de noms de variables trouvés avec tant de finesse).
    Ensuite tu n'as pas suffisamment travaillé ton chapitre sur les classes de ton tutoriel. Travailler un chapitre c'est le lire mais aussi retaper les exemples qui y sont et examiner leur fonctionnement pour les comprendre. Rien que le fait que tu dises "j'ai du mal avec self" montre que tu n'as absolument rien compris des classes et des instances de classe de Python (c'est comme si tu avais dit "dans n=1/0 j'ai du mal avec n").
    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]

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

    Citation Envoyé par olivbarb59 Voir le message
    Pourriez-vous m'expliquer ce que je fais mal afin de progresser ?
    self est la variable locale définie par le premier argument de toute méthode d'un objet.
    Par convention, il représente l'objet courant lorsqu'on exécute une (de ses) méthodes.
    Convention qu'on s'applique à respecter, histoire de faciliter la lecture de son code.


    Si on écrit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            if len(nom_entite) == 0:
                initialisation.Initialisation.init(self)
    Initialisation.init sera la fonction (pas la méthode) appelée avec self (instance de Marche).
    note: pour être méthode, il aurait fallu instancier un objet Initialisation avant via X = initialisation.Initialisation(self), puis appeler la méthode init via X.init()Du coup, dans Initialisation.init, ce self n'est pas une instance d'Initialisation mais ça reste une instance de Marche.
    Ecrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            self.initialisation = tkinter.Toplevel()
            ...
    ajoute l'attribut initialisation à cette instance de Marche (et non à l'instance d'Initialisation).
    Et il aurait été plus correct de nommer cette variable "marche" plutôt que "self"...

    note: L'intérêt de la POO est de pouvoir confiner le contrôle des objets aux méthodes de leur classe. Modifier l'objet depuis un objet tiers est quelque chose qu'on s'interdira en écrivant self.initialisation = initialisation.Initialisation(self) (dans Marche) plutôt qu'aller triturer une instance de Marche dans Initialisation.

    Arrivé là, self.initialisation n'étant pas un objet Initialisation, il n'a pas de méthode valider_ajout_premiere_entite qui aurait pu s'accéder via self.valider_ajout_premiere_entite (si self n'était pas un Marche).

    Que faites vous de "mal"? En fait, vous devez être convaincu d'avoir pensé correctement le découpage de votre code avant de vous lancer à écrire quoi que ce soit.... vous méfier de fausses bonnes idées qui marchotent ici ou là et surtout apprendre à relire ce que vous avez écrit/codé: la machine se contente d'exécuter ce qu'on lui demande.

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

  4. #4
    Candidat au Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Mai 2022
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Mai 2022
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Merci de vos réponses, je reprends mes tutos tout de suite car je crois que je n'ai rien compris aux classes. J'en suis même sûr.

    Mais ce qui me fait bizarre, c'est que j'ai voulu "simplifier" mon code en faisant plusieurs fichiers qui ne feraient qu'une action : un fichier principal, un fichier qui teste, un fichier qui affiche, ... Et c'est là que ça pose pb car si je mets toutes les méthodes dans une seule classe je n'ai pas de pb.

    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
    import tkinter.ttk
    import tkinter
    import tkinter.messagebox
    import datetime
    import os
     
    class Marche(tkinter.Tk):
        def __init__(self):
            tkinter.Tk.__init__(self)
     
            nom_entite, distance_entite = importation_entite()
     
            if len(nom_entite) == 0:
                self.init()
     
        def init(self):
     
            # caracteristique de la fenetre principale
            self.initialisation = tkinter.Toplevel()
            self.initialisation.geometry("400x200")
            self.initialisation.resizable(width=False, height=False)
     
            self.initialisation.lTitre = tkinter.ttk.Label(self.initialisation, text="Aucune entit├® n'est enregistr├®e, il en faut au moins une.", font='bold')
            self.initialisation.lEntite = tkinter.ttk.Label(self.initialisation, text="Quel est le nom de l'entit├® :")
            self.initialisation.eEntite = tkinter.ttk.Entry(self.initialisation)
            self.initialisation.lDistance = tkinter.ttk.Label(self.initialisation, text="Quelle est la distance parcourue :")
            self.initialisation.sDistance_Entite = tkinter.ttk.Spinbox(self.initialisation, from_=0.0, to=50.0, increment=0.1, width=5)
     
            self.initialisation.bValider = tkinter.ttk.Button(self.initialisation, text="Valider", command=self.valider_ajout_premiere_entite)
     
            self.initialisation.lTitre.place(x=10, y=10)
            self.initialisation.lEntite.place(x=10, y=40)
            self.initialisation.eEntite.place(x=10, y=60)
            self.initialisation.lDistance.place(x=10, y=100)
            self.initialisation.sDistance_Entite.place(x=10, y=120)
            self.initialisation.bValider.place(x=10, y=160)
     
        def valider_ajout_premiere_entite(self):
            if self.initialisation.eEntite.get() == "" or self.initialisation.sDistance_Entite.get() == "":
                tkinter.messagebox.showerror("Erreur", "Une des 2 valeurs n'a pas ├®t├® correctement renseign├®es")
            else:
                chemin_distance = os.path.join(os.path.dirname(__file__), "distance")
     
                # on ajoute la premiere valeur au fichier distance
                with open(chemin_distance, "w") as data:
                    data.write(f"{entite} {self.initialisation.sDistance_Entite.get()}\n")
     
                self.initialisation.destroy()
     
     
     
    def importation_entite():
        nom_entite = ""
        distance_entite = ""
        chemin_distance = os.path.join(os.path.dirname(__file__), "distance")
        with open(chemin_distance, "r") as distance:
            for dist in distance:
                nom_entite += dist.split()[0] + " :\n"
                distance_entite += dist.split()[1] +" km\n"
        return nom_entite, distance_entite

  5. #5
    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
    Citation Envoyé par olivbarb59 Voir le message
    Mais ce qui me fait bizarre, c'est que j'ai voulu "simplifier" mon code en faisant plusieurs fichiers qui ne feraient qu'une action : un fichier principal, un fichier qui teste, un fichier qui affiche, ... Et c'est là que ça pose pb car si je mets toutes les méthodes dans une seule classe je n'ai pas de pb.
    On ne peut pas découper son code comme on le veut: il y a des "règles" et du bon sens.

    Apprenez déjà à le découper en fonctions... et profitez du fait que tkinter ne vous impose pas de toucher au "class" pour ne les utiliser que lorsque ça fait du sens (et pas pour faire joli ou rouler les mécaniques).

    Passez aussi du temps à apprendre les bases de tkinter: place est à utiliser avec précaution, facile mais une présentation difficile à maintenir.... car vous n'allez pas sortir une feuille de papier millimétré pour calculer la position de vos différents widgets à chaque changement.

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

  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 olivbarb59 Voir le message
    Mais ce qui me fait bizarre, c'est que j'ai voulu "simplifier" mon code en faisant plusieurs fichiers qui ne feraient qu'une action : un fichier principal, un fichier qui teste, un fichier qui affiche, ...
    Ca c'est une très bonne idée.

    Citation Envoyé par olivbarb59 Voir le message
    Et c'est là que ça pose pb car si je mets toutes les méthodes dans une seule classe je n'ai pas de pb.
    Hé oui, car l'import peut, selon la façon dont il est fait, changer pas mal de choses.

    Prenons une fonction simple: un carré
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def carre(n): return n**2
     
    for i in range(10): print(i, carre(i))

    Tu veux le découper selon ta vision qui sera "le travail d'un côté, l'affichage de l'autre" (ce qui est l'ersatz de la programmaton MVC). Tu vas placer ta fonction "carre" dans un fichier "travail.py" =>
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    def carre(n): return n**2

    Maintenant tu dois importer ce "travail.py" et c'est là que l'import entre en jeu.
    Soit tu importes directement la fonction et dans ce cas la fonction est directement utilisable par son nom
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    from travail import carre
     
    for i in range(10): print(i, carre(i))

    ... soit tu importes tout le contenu du fichier et pareil...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    from travail import *
     
    for i in range(10): print(i, carre(i))

    ... soit tu importes le fichier et là la fonction est vue comme étant dans le fichier importé => il faut rajouter le nom du fichier pour l'utiliser
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    import travail
     
    for i in range(10): print(i, travail.carre(i))

    Cette dernière solution semble plus contraignante mais montre son efficacité lors des imports multiples. Imagine que tu importes X (qui contient une fonction "carre") et que tu importes Y (qui contient lui-aussi une fonction "carre" mais différente) ? C'est parfaitement possible. Les programmeurs de X et Y ne bossent pas ensembles, chacun d'eux peut très bien avoir développé sa propre fonction "carre"...

    La gestion des noms de fonctions (et objets) se nomme "namespace". En faisant from truc import * tu importes tout le contenu de "truc" dans l'espace "principal" de ton code et en faisant import truc tu crées un second namespace disponible nommé "truc" qui, lui, contient le code de truc.
    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
    Candidat au Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Mai 2022
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Mai 2022
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    C'est tout des noms que j'ai déjà entendu mais je n'ai pas du bien assimiler les fonctions !
    Si cela peut servir à d'autres personnes qui voudraient se mettre au python, tant mieux.

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

Discussions similaires

  1. [Python 2.X] python self.pk ça sert à quoi
    Par hichem0550 dans le forum Général Python
    Réponses: 2
    Dernier message: 24/11/2016, 11h37
  2. Réponses: 6
    Dernier message: 17/08/2013, 18h41
  3. CORBA & PYTHON
    Par stan91stan dans le forum CORBA
    Réponses: 5
    Dernier message: 10/06/2004, 12h32
  4. [Lien]erreur dans mon programme python
    Par durnambule dans le forum Général Python
    Réponses: 11
    Dernier message: 29/01/2004, 14h59
  5. PB avec "self" dans une dll
    Par DiJiRiDouS dans le forum Langage
    Réponses: 2
    Dernier message: 21/02/2003, 09h32

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