Frage

Ich versuche, ein Python 2.7-Tkinter-Modul zu erstellen, das Skalierungs-Widget-Daten verwendet, um ein Listenverständnis zu beeinflussen, das zwischen Tieren auswählt, deren Wahrscheinlichkeitsmerkmale als Liste von Listen dargestellt werden.Das Modul sortiert und zeigt die drei Tiere in absteigender Reihenfolge an, wenn Sie auf "Senden" klicken und den zugehörigen Befehl aktivieren.

In diesem Beispiel sind alle drei Tiere nach dem Klicken auf "Senden" bei 33%, da sie dieselben Wahrscheinlichkeitsdaten haben.Die Tiere unterscheiden sich nur zwischen den Skalen-Widget-Daten in Spalte 2 der Liste der Listen darin, dass jedes entweder aquatisch, terrestrisch oder beides ist.

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()

Dank vieler Verbesserungen funktioniert dieser Code!

War es hilfreich?

Lösung

Das erste, was mir auffällt, ist, dass Sie A als leeres Wörterbuch definieren und dieses leere Wörterbuch dann mit self.animal überschreiben, bei dem es sich um eine Liste handelt.

    A={}
    A=self.animal

Ich bin mir also nicht sicher, was Sie hier vorhaben. Dann schneiden Sie es in Ihrer Definition von B in Scheiben:

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

Dies entspricht nicht der entweder -Definition von A, da Sie kein Diktat aufteilen können, der von Ihnen gewählte Startindex jedoch 3 ist und der höchste Index in self.animal 2 ist. Verwirrend! Bei näherer Betrachtung wird jedoch deutlich, dass das Problem darin besteht, dass Sie A als Indexvariable wiederverwenden. Sie sollten das wirklich nicht tun. es macht diesen Code unglaublich verwirrend.

Es kann auch Fehler verursachen. Betrachten Sie diesen Code:

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

Wie Sie sehen können, verweist das Listenverständnis aufgrund des Listenverständnisses auf den letzten Wert in der Sequenz, die zuvor als a bezeichnet wurde. Dies passiert in Ihrem Code nicht, weil Sie einen Generatorausdruck verwendet haben. Aber es ist immer noch schwer zu lesen und verwirrend. Ich empfehle dringend, dies stattdessen zu tun:

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

Update : OK, nachdem Sie diese Änderungen vorgenommen haben, müssen Sie die Daten von der Waage noch generisch codieren. In Ihrer Definition von a verwenden Sie get wie folgt:

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

Dies setzt den Rückgabewert von self.animal in ein Tupel. Aber dann ist dieser Wert festgelegt - er wird sich nie ändern. Sie müssen self.soil.get() jedes Mal explizit aufrufen, wenn Sie den aktualisierten Wert wünschen. Außerdem greifen Ihre Listenverständnisse niemals auf den dort zurückgegebenen Wert zu. Sie schneiden sie wie folgt:

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

Denken Sie daran, dass die Indizierung in Listen und Tupeln mit self.soil.get() beginnt - also im obigen Tupel self.soil.get(), 0. Wenn Sie also alles außer den ersten beiden Dingen wollen, müssen Sie aus Index 2 herausschneiden:

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

Damit ist das Grundproblem jedoch immer noch nicht gelöst. Sie müssen l aufrufen, um die aktualisierten Daten zu erhalten. Eine Möglichkeit, dies zu tun, besteht darin, den l[0] == 'Odocoileous virginiana' jedes Mal neu zu erstellen, wenn die Senden-Schaltfläche gedrückt wird. Das wäre verschwenderisch, aber es würde funktionieren. Ein weniger verschwenderischer (aber immer noch umständlicher) Ansatz wäre, die Funktion selbst im Tupel zu speichern, anstatt das Ergebnis der Funktion. Sie würden das so machen:

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

Beachten Sie das Fehlen von self.soil.get() nach self.animal. Jetzt enthält das Tupel keinen Gleitkommawert, sondern eine Funktion, die einen Gleitkommawert zurückgibt. Sie müssen es aufrufen, um den Wert zu erhalten, aber es gibt jedes Mal den vollständig aktualisierten Wert zurück. Um Funktionen zu kombinieren, können Sie () verwenden:

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

Jetzt können Sie self.soil.get aufrufen, um einen Wert zu erhalten:

>>> l[2]()
0.30250000000000005

Um alles zusammenzufassen, müssen Sie das Listenverständnis etwas weiter aufteilen, um lambda explizit aufzurufen. Sobald Sie dies getan haben, sollte dies funktionieren. Dies ist kein ideales Setup, aber ich fürchte, ich muss die Erstellung einer verbesserten Architektur als Übung für den Leser verlassen.

Andere Tipps

A[2][i]/sigma*A[2][i] Dieses Bit versucht, den Float zu indizieren. Sollte dies sein: stattdessen A[i]/sigma*A[i]?

Ich habe angenommen, dass die Werte in A alle Gleitkommazahlen sind.

Der for A in A-Teil erscheint mir etwas zwielichtig.Es mag syntaktisch korrupt sein, aber es ist normalerweise klarer, unterschiedliche Namen für Sammlungen und Elemente in diesen Sammlungen zu verwenden.

Auch for isolates in A: i = A.index(isolates) kann durch Verwendung von for i, isolates in enumerate(A) wesentlich effektiver gestaltet werden, da A.index(isolates) lange dauern kann, wenn A groß ist.

Ich weiß, keine wirkliche Antwort auf Ihre Frage, aber ich hoffe, dass es trotzdem nützlich ist.

Um das Debuggen zu vereinfachen (und Ihnen tatsächlich zu helfen), schreiben Sie Folgendes um:

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

in etwas etwas lesbareres.Wenn Sie es in etwas mit mehreren Zeilen aufteilen, können Sie tatsächlich einen Debugger verwenden und leicht sehen, welche Variable ein 'float' ist und wo sie indiziert wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top