Question

J'essaie de créer un module Python 2.7 Tkinter qui utilise des données de widget d'échelle pour influencer une compréhension de la liste qui sélectionne entre les animaux dont les traits de probabilité sont représentés comme une liste de listes. Le module trie et affiche les trois animaux dans l'ordre descendant classé en cliquant sur «Soumettre» et en activant la commande associée.

Dans cet exemple, les trois animaux sont à 33% après avoir cliqué sur «soumettre» car ils partagent les mêmes données de probabilité. Les animaux ne diffèrent que les données du widget d'échelle dans la colonne 2 de la liste des listes en ce que chacun est aquatique, terrestre ou les deux.

from Tkinter import BOTH, BOTTOM, Button, E, END, Entry, FLAT, Frame, Grid, HORIZONTAL, Label, LEFT, N, NO, Pack, RAISED, RIGHT, S, Scale, Text, Tk, TOP, W, YES

from operator import mul

root = Tk()
root.title('Example')

class Environment:
    def __init__(self, parent):

        # layout
        self.myParent = parent

        self.main_frame = Frame(parent, background="light blue")
        self.main_frame.pack(expand=YES, fill=BOTH)

        self.main_left_frame = Frame(self.main_frame, background="light blue")
        self.main_left_frame.pack(side=LEFT, expand=YES, fill=BOTH)

        self.main_right_frame = Frame(self.main_frame, background="light blue")
        self.main_right_frame.pack(side=RIGHT, expand=YES, fill=BOTH)

        self.water = Scale(self.main_right_frame, from_=0.01, to=1.00, orient=HORIZONTAL, bd=0, label="Aquatic",
        background="white", troughcolor="cyan", length=50, width=10, sliderlength=10, resolution=0.01)
        self.water.pack()
        self.water.set(1.00)

        self.soil = Scale(self.main_right_frame, from_=0.01, to=1.00, orient=HORIZONTAL, bd=0, label="Terrestrial",
        background="white", troughcolor="saddle brown", length=50, width=10, sliderlength=10, resolution=0.01)
        self.soil.pack()
        self.soil.set(1.00)

        self.id_frame = Frame(self.main_left_frame, background="white")
        self.id_frame.pack(side=BOTTOM)

        # submit button
        self.submitbutton = Button(self.main_left_frame,text="Submit", background="black", foreground="white",
        width=6, padx="2m", pady="1m")
        self.submitbutton.pack(side=TOP)
        self.submitbutton.bind("<Button-1>", self.submitbuttonclick)
        self.submitbutton.bind("<Return>", self.submitbuttonclick)

        #Animal Matrix
        self.animal = [
        ('Odocoileous virginiana','White-tailed Deer',self.soil.get,0.99,0.01,0.99),
        ('Anguilla anguilla','American Eel',self.water.get,0.99,0.01,0.99),
        ('Trachemys scripta','Slider',lambda:self.soil.get()*self.water.get(),0.99,0.01,0.99)]

    def submitbuttonclick(self, event):
        self.id_frame.destroy()
        self.id_frame = Frame(self.main_left_frame, background="white")
        self.id_frame.pack(side=BOTTOM)

        A=self.animal

        #equation
        sigma = float(sum(reduce(mul,item[3:]) for item in A))
        B = [(item[0], "%.2f" % (item[2]()*reduce(mul, item[3:])/sigma)) for item in A]
        C = sorted(B, key=lambda item: item[1], reverse=True)  

        Label(self.id_frame, text = C[0], background = "white").pack(side=TOP, anchor = W)
        Label(self.id_frame, text = C[1], background = "white").pack(side=TOP, anchor = W)
        Label(self.id_frame, text = C[2], background = "white").pack(side=TOP, anchor = W)

environment = Environment(root)       
root.mainloop()

Grâce à de nombreuses améliorations contribuées, ce code fonctionne!

Était-ce utile?

La solution

La première chose que je remarque, c'est que vous définissez A être un dictionnaire vide, puis écraser ce dictionnaire vide avec self.animal, qui est une liste.

    A={}
    A=self.animal

Je ne sais donc pas ce que vous voulez faire ici. Puis dans votre définition de B vous le coupez:

    B = [(A[0], "%.2f" % (reduce(mul,A[3:])*A[2][i]/sigma*A[2][i])) for A in A]

Cela ne se caractérise pas avec Soit Définition de A, parce que vous ne pouvez pas couper un dict, mais l'indice de départ que vous avez choisi est 3, et l'indice le plus élevé en self.animal est 2. Déroutant! Mais en regardant de plus près, il devient clair que le problème est que vous réutilisez A comme variable d'indexation. Tu vraiment ne devrait pas faire ça; ça fait ce code incroyablement déroutant.

Cela peut également provoquer des erreurs. Considérez ce code:

>>> a = range(10)
>>> [a for a in a]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a
9

Comme vous pouvez le voir, la compréhension de la liste provoque a Pour se référer à la dernière valeur de la séquence auparavant connue sous le nom a. Cela ne se produit pas dans votre code car vous avez utilisé une expression de générateur. Mais c'est encore difficile à lire et à déroutant. je fortement recommande de faire cela à la place:

    sigma = float(sum(reduce(mul,item[3:]) for item in A))
    B = [(item[0], "%.2f" % (reduce(mul,item[3:])/sigma)) for item in A] 

Mise à jour: Ok, après avoir apporté ces modifications, vous devez toujours get les données des échelles. Dans votre définition de self.animal, tu utilises self.soil.get(), ainsi:

('Odocoileous virginiana','White-tailed Deer',self.soil.get(),0.99,0.01,0.99)

Cela met la valeur de retour de self.soil.get() dans un tuple. Mais alors cette valeur est fixée - elle ne changera jamais. Vous devez appeler explicitement self.soil.get() à chaque fois Vous voulez la valeur mise à jour. De plus, vos compréhensions de la liste n'accèdent jamais à la valeur renvoyée là-bas. Vous les coupez comme ça:

>>> l = ('Odocoileous virginiana','White-tailed Deer',
...      self.soil.get(), 0.99, 0.01, 0.99)
>>> l[3:]
(0.98999999999999999, 0.01, 0.98999999999999999)

N'oubliez pas que l'indexation dans les listes et les tuples commence par 0 - donc dans le tuple ci-dessus l, l[0] == 'Odocoileous virginiana'. Donc, si vous voulez tout sauf les deux premières choses, vous devez trancher de l'index 2:

>>> l[2:]
(0.55000000000000004, 0.98999999999999999, 0.01, 0.98999999999999999)

Mais cela ne résout toujours pas le problème racine, c'est que vous devez appeler self.soil.get() pour obtenir les données mises à jour. Une façon de le faire est simplement en recréant self.animal Chaque fois que le bouton Soumettre est appuyé. Ce serait un gaspillage mais cela fonctionnerait. Une approche moins inutile (mais toujours maladroite) serait de sauver la fonction elle-même dans le tuple, au lieu du résultat de la fonction. Tu le ferais comme tel:

>>> l = ('Odocoileous virginiana','White-tailed Deer',
...      self.soil.get, 0.99, 0.01, 0.99)

Notez l'absence de () après self.soil.get. Maintenant, le tuple ne contient pas une valeur de point flottante, mais une fonction qui renvoie une valeur de point flottante. Vous devez l'appeler pour obtenir la valeur, mais il renvoie la valeur entièrement mise à jour à chaque fois. Pour combiner des fonctions, vous pouvez utiliser lambda:

>>> l = ('Odocoileous virginiana','White-tailed Deer',
...      lambda: self.soil.get() * self.water.get(), 0.99, 0.01, 0.99)

Maintenant tu peux appeler l[2] Pour obtenir une valeur:

>>> l[2]()
0.30250000000000005

Donc, pour tout mettre ensemble, vous devez briser un peu plus la compréhension de la liste pour appeler explicitement l[2], mais une fois que vous avez fait cela, cela devrait fonctionner. Ce n'est pas une configuration idéale, mais j'ai peur de quitter la création d'une architecture améliorée comme exercice pour le lecteur.

Autres conseils

A[2][i]/sigma*A[2][i]Ce bit essaie d'indexer le flotteur. Cela devrait être: A[i]/sigma*A[i] Au lieu?

J'ai fait l'hypothèse que les valeurs dans A sont tous des flotteurs.

La for A in A La partie me semble un peu douteuse. Il peut être syntaxiquement corrent, mais il est utile d'utiliser différents noms pour les collections et les éléments de ces collections.

Aussi for isolates in A: i = A.index(isolates) peut être rendu beaucoup plus efficace en utilisant for i, isolates in enumerate(A), comme A.index(isolates) Peut prendre beaucoup de temps où A est grand.

Je sais, pas vraiment une réponse à votre question, mais j'espère que c'est néanmoins utile.

Pour faciliter le débogage (et pour vous aider), veuillez réécrire ceci:

[(A[0], "%.2f" % (reduce(mul,A[3:])*A[2][i]/sigma*A[2][i])) for A in A]

dans quelque chose d'un peu plus lisible. Si vous le divisez en quelque chose avec plusieurs lignes, vous pouvez réellement utiliser un débogueur et voyez facilement quelle variable est un «flotteur» et où il est indexé.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top