Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 28/11/2008, à 22:46

Ncmorin

Petit problème de débutant en Python..

Bonjour tout le monde!:D

Alors voilà, j'expose mon problème.:o
Je débute tout juste en python et je suis en train de développer un programme de calcul de coefficients u et v de l'égalité de bezout. (C'est dans mon programme de terminale scientifique en spécialité maths.)
L'algorithme ne me pose pas de problème, j'ai déja fait le programme sur ma TI-84 plus.
Ce qui me pose problème c'est tkinter... roll
J'ai réussi à faire en sorte d'entrer les deux variables, de les enregistrer, de faire les calculs pour trouver U et V, et maintenant je voudrais afficher u et v, mais je n'y arrive pas..

Je vous poste mon code:

#!/usr/bin/python
# -*- coding: iso-8859-1 -*-

from Tkinter import *
F=0
# --- Définition de la fonction Bezout ---
def bezout():
    c=1
    d=0
    g=0
    F=1
    h=1
    while s!=0:
        q=(petita/petitb)
        e=c
        c=d
        d=e-d*q
        i=g
        g=h
        h=i-h*q
        t=petita
        petita=petitb
        petitb=t-petitb*q
# --- r est le PGCD de a et b; c est U, et G est V ---

fen1 = Tk()
fen1.title("Coefficients De Bezout")
petita = IntVar()
petitb = IntVar()
Txt1 = Label(fen1,text="Entrez Le Nombre A : ")
Txt1.grid(row=0,column=1)
Txt2 = Label(fen1,text="Entrez Le Nombre B : ")
Txt2.grid(row=1,column=1)
NombreA = Entry(fen1, textvariable = petita)
NombreA.grid(row=0,column=2)
NombreB = Entry(fen1, textvariable = petitb)
NombreB.grid(row=1,column=2)
boutton = Button(fen1, text="Valider", command = bezout())
boutton.grid(row=3,column=1)
if F==1:
    resulte = Label(fen1,text = ("u et v sont : ",c," et ",g))
    resulte.grid(row=4)
fen1.mainloop()

Merci de votre aide!:P

#2 Le 28/11/2008, à 23:23

twinsen93

Re : Petit problème de débutant en Python..

Il manque d'abord des objets graphiques pour afficher les résultats. Des Entry par exemple :

grandU = IntVar()
grandV = IntVar()
Txt3 = Label(fen1,text="U : ")
Txt3.grid(row=4,column=1)
Txt4 = Label(fen1,text="V : ")
Txt4.grid(row=5,column=1)
NombreU = Entry(fen1, textvariable = grandU)
NombreU.grid(row=4,column=2)
NombreV = Entry(fen1, textvariable = grandV)
NombreV.grid(row=5,column=2)

Puis, ta procédure bezout() qui est appelée sur le clic du bouton doit placer les résultats :

grandU.set(c)
grandV.set(g)

Hors ligne

#3 Le 28/11/2008, à 23:43

Ncmorin

Re : Petit problème de débutant en Python..

Merci d'avoir répondu aussi vite, mais il doit y avoir un malentendu..
U et V sont deux nombres que l'on cherche.
En fait l'égalité de bezout est: au+bv=pgcd(a,b)
et on connai a et b (qui sont appelé petita et petitb dans mon code), ce sont les variables que l'utilisateur entre.
et une fois que l'algo "bezout" est fini, les nombres u et v sont dans les variables c et g..

#4 Le 28/11/2008, à 23:52

twinsen93

Re : Petit problème de débutant en Python..

Ncmorin a écrit :

U et V sont deux nombres que l'on cherche.

J'ai bien compris. D'ou le

grandU.set(c)
grandV.set(g)

à placer à la fin de bezout().

J'ai suggéré d'utiliser un Entry, mais tu peux utiliser un Label à la place.

PS : le code que tu as posté ne fonctionne pas
PS2: le bezout() que tu as écris n'est pas une fonction mais une procédure. C'est effectivement une bonne idée d'en faire une fonction en précisant les paramètres a et b et en retourant u et v, ca donne un meilleur découplage à ton code.
PS3 : wikipedia m'informe que cet algo est communément appelé Euclide étendu au lieu de Bezout

Hors ligne

#5 Le 29/11/2008, à 01:32

twinsen93

Re : Petit problème de débutant en Python..

Voila a quoi ressemble une réecriture du code a ma sauce.  J'ai écris l'algo dans une procédure, je l'ai séparé de l'interface graphique, j'ai mis cette dernière dans un objet.

#!/usr/bin/python

from Tkinter import Tk, Frame, Label, Entry, Button, IntVar


def euclide_etendu(a, b):
    #if (a < b): a, b = b, a # algorithme plus rapide si a et b sont dans le bon ordre
    # initialisation
    r,  u,  v  = a, 1, 0
    r1, u1, v1 = b, 0, 1
    # invariant
    # r  = a*u  + b*v
    # r1 = a*u1 + b*v1
    while r1 != 0:
        u, u1 = u1,  u - (r / r1) * u1
        v, v1 = v1,  v - (r / r1) * v1
        r, r1 = r1,  r % r1
    return r, u, v


class MainFrame(Frame):
    
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.createWidgets()
    
    def createWidgets(self):
        row = 0
        self.var_a = IntVar()
        Label(self,text="Entrez Le Nombre A : ").grid(row=row, column=1)
        Entry(self, textvariable = self.var_a).grid(row=row, column=2)
        
        row += 1
        self.var_b = IntVar()
        Label(self,text="Entrez Le Nombre B : ").grid(row=row, column=1)
        Entry(self, textvariable = self.var_b).grid(row=row, column=2)
        
        row += 1
        Button(self, text="Valider", command=self.onClick).grid(row=row, column=1, columnspan=2)
        
        row += 1
        self.var_u = IntVar()
        Label(self,text="Nombre U : ").grid(row=row, column=1)
        Entry(self, textvariable = self.var_u).grid(row=row, column=2)
        
        row += 1
        self.var_v = IntVar()
        Label(self,text="Nombre V : ").grid(row=row, column=1)
        Entry(self, textvariable = self.var_v).grid(row=row, column=2)
        
    def onClick(self):
        a, b = self.var_a.get(), self.var_b.get()
        r, u, v = euclide_etendu(a, b)
        self.var_u.set(u)
        self.var_v.set(v)

if __name__ == '__main__':
    master = Tk()
    main_frame = MainFrame(master)
    main_frame.mainloop()

Hors ligne

#6 Le 29/11/2008, à 23:20

Ncmorin

Re : Petit problème de débutant en Python..

Ah d'accord, merci!:D
Je ne savais pas que ça s'appelait comme ça.. On a vu comment faire le calcul sur papier en classe de spécialité maths et je l'ai juste traduit par un petit algo sur ma caltos à la base.. Et on m'a parlé du python la semaine dernière, ça fait exactement 6 jours que j'ai commencé le python! yikes
Je vais essayer de le refaire un peu mieux, mais par contre je n'arrivais pas à faire marcher mon bout de code si je mettais bezout(r,s) et que le boutton activais bezout(petita,petitb) (car au débu je n'avais pas de petita et petitb dans bezout(), ces variables s'appelaient r et s)
En tout cas merci beaucoup!

#7 Le 29/11/2008, à 23:24

Ncmorin

Re : Petit problème de débutant en Python..

Je viens de tester ton code, ça marche génial!:lol: Gràce à toi je vais beaucoup apprendre!
Seulement j'aurais aimé pourvoir faire une phrase, enfin j'aurais aimé.. Pour voir comment est-ce qu'on peut faire! Plus j'en apprend sur Python, et plus j'aime ce langage!

#8 Le 29/11/2008, à 23:39

Ncmorin

Re : Petit problème de débutant en Python..

Bon, je vais essayer de comprendre ton code..



class MainFrame(Frame):                   |
                                                    |
    def __init__(self, master=None):     |   Je ne comprend pas comment
        Frame.__init__(self, master)       |   fonctionne cette partie
        self.pack()                              |
        self.createWidgets()                 |
   
    def createWidgets(self):                |   Pourquoi le "self" de createWidgets(self) ?
        row = 0
        self.var_a = IntVar()
        Label(self,text="Entrez Le Nombre A : ").grid(row=row, column=1)
        Entry(self, textvariable = self.var_a).grid(row=row, column=2)
       
        row += 1
        self.var_b = IntVar()
        Label(self,text="Entrez Le Nombre B : ").grid(row=row, column=1)
        Entry(self, textvariable = self.var_b).grid(row=row, column=2)
       
        row += 1
        Button(self, text="Valider", command=self.onClick).grid(row=row, column=1, columnspan=2)
       
        row += 1
        self.var_u = IntVar()
        Label(self,text="Nombre U : ").grid(row=row, column=1)
        Entry(self, textvariable = self.var_u).grid(row=row, column=2)
       
        row += 1
        self.var_v = IntVar()
        Label(self,text="Nombre V : ").grid(row=row, column=1)
        Entry(self, textvariable = self.var_v).grid(row=row, column=2)
       
    def onClick(self):
        a, b = self.var_a.get(), self.var_b.get()
        r, u, v = euclide_etendu(a, b)
        self.var_u.set(u)
        self.var_v.set(v)

if __name__ == '__main__':          |   Je ne comprend pas cette ligne non plus..
    master = Tk()
    main_frame = MainFrame(master)        |  Ici je ne comprend pas d'ou vient le "master"..
    main_frame.mainloop()



Merci beaucoup de prendre de ton temps pour moi

#9 Le 30/11/2008, à 11:15

twinsen93

Re : Petit problème de débutant en Python..

Ncmorin a écrit :

Plus j'en apprend sur Python, et plus j'aime ce langage!

Moi pareil ! Python c'est bôooo.

Si tu en est à  6 semaines de python et que tu débutes la programmation, je me dois de te donner l'explication détaillée.

Commencons par

class MainFrame(Frame)

J'ai décidé de créer un objet (un objet logique, un découpage du programme) qui contiendra la boite de dialogue. L'avantage, c'est que tout ce qui concerne la boite de dialoque est encapsulé dans cet objet. Ca limite les couplages entre cette partie du code et le reste, donc ca facilite le débugage et les modifications.

A cet endroit, je déclare la classe de mon objet (le modèle sur lequel il est construit), et plus loin

main_frame = MainFrame(master)

Je crée l'objet lui même. Jeu peux alors utiliser une fonction encapsulée dans l'objet (qui s'appelle un méthode de l'objet):

main_frame.mainloop()

Ici, mainloop() est une méthode de main_frame, mais ce n'est pas moi qui l'ai codée : quand j'ai créé ma classe MainFrame, j'ai précisé entre parenthèse qu'elle hérite de Frame (importé de Tkinter), donc l'objet contient aussi les méthodes de Frame.
C'est le deuxième avantage de la programmation objet : ca facilite la réutilisation du code.

Maintenant, venons en au "self". Pas la peine de prendre un plateau, il n'y a rien à manger ici. L'objet ne contient pas seulement des méthodes, il a également un état interne, stokcé dans des variables internes à l'objet. Le "self" qui est passé en paramètre à toutes les méthodes de l'objet est l'objet lui même et permet d'accéder a ces variables internes (et aussi d'appeler une méthode depuis une autre).

Vient ensuite le __init__. L'idée est que les variables internes de l'objet forment un état cohérent, ce qui implique :
1. les méhodes qui les manipulent doivent garder un état cohérent
2. à la création de l'objet, elles doivent être initialisées pour former un état cohérent
C'est le rôle de __init__, cette méthode au nom spécial est appelée juste après la création de l'objet.

La première ligne

Frame.__init__(self, master)

appelle cette même méthode d'initialisation, mais de la classe parente Frame. Comme MainFrame est un type particulier de Frame, l'état interne de l'objet doit être initialisé comme celui d'un objet Frame.

Pour finir

if __name__ == '__main__':

Permet de n'exécuter un code que si on est dans le module principal. La variable __name__ contient le nom avec lequel le module a été importé. Si tu déplace le code de MainFrame dans un fichier main_frame.py, tu peux mettre dans main_frame.py un if __name__ == '__main__' avec un bout de code qui teste l'interface graphique. Si tu execute main_frame.py ce code de test sera exécuté, mais si tu éxécute ton programme principal qui utilise MainFrame en faisant un import main_frame, non.

Le master est le résultat de la fonction Tk() de Tkinter. C'est la fenêtre créée par l'initialisation de Tk. On la passe en paramètre à la création de MainFrame pour qu'elle vienne s'afficher dans la fenêtre principale.

Un mot sur la fonction euclide_etendu(). Tu peux lire un commentaire qui parle de l'invariant. C'est LA méthode pour concevoir un algorithme.

Il faut trouver un énoncé qui va rester vrai tout au long de l'éxécution et qui permet de trouver le résultat.

Ensuite, on cherche la condition d'arrêt. Combinée avec l'invariant, elle doit donner le résultat.

On a besoin d'une initialisation qui respecte l'invariant :

Enfin, à chaque étape, on fait évoluer les variables pour conserver l'invariant vrai tout en se rapprochant de la solution. Ici

u, u1 = u1,  u - (r / r1) * u1
v, v1 = v1,  v - (r / r1) * v1
r, r1 = r1,  r % r1

forme une étape. L'invariant n'est plus vrai au milieu mais redevient vrai à la fin.

Voila, j'attends tes questions.

Hors ligne

#10 Le 30/11/2008, à 19:29

Ncmorin

Re : Petit problème de débutant en Python..

Merci beaucoup! Je comprend beaucoup mieux!
Et je tiens à préciser que ça ne fait pas 6 semaines que j'ai commencé le python, mais 6 jours! enfin 7 aujourd'hui..:D
Merci beaucoup de prendre autant de temps pour tout m'expliquer en détail. Je relirais mieux ton explication plus tard, pour vraiment bien comprendre. Encore merci.