Domanda

Sto cercando di creare un modulo python 2.7 tkinter che utilizza i dati del widget di scala per influenzare una comprensione di elenchi che seleziona tra animali i cui tratti di probabilità sono rappresentati come un elenco di elenchi.Il modulo ordina e visualizza i tre animali in ordine decrescente facendo clic su "Invia" e attivando il comando associato.

In questo esempio, tutti e tre gli animali sono al 33% dopo aver fatto clic su "Invia" perché condividono gli stessi dati di probabilità.Gli animali differiscono solo tra i dati del widget di scala nella colonna 2 dell'elenco degli elenchi in quanto ciascuno è acquatico, terrestre o entrambi.

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

Grazie a molti miglioramenti apportati, questo codice funziona!

È stato utile?

Soluzione

La prima cosa che noto è che definisci A come un dizionario vuoto, quindi sovrascrivi quel dizionario vuoto con self.animal, che è un elenco.

    A={}
    A=self.animal

Quindi non sono sicuro di cosa intendi fare qui. Quindi nella tua definizione di B lo dividi:

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

Questo non quadra con neanche la definizione di A, perché non puoi suddividere un dict, ma l'indice iniziale che hai scelto è 3 e l'indice più alto in self.animal è 2. Confondere! Ma guardando più da vicino, diventa chiaro che il problema è che stai riutilizzando A come variabile di indicizzazione. davvero non dovresti farlo; rende questo codice incredibilmente confuso.

Può anche causare errori. Considera questo codice:

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

Come puoi vedere, la comprensione dell'elenco fa sì che a si riferisca all'ultimo valore nella sequenza precedentemente nota come a. Questo non accade nel tuo codice perché hai usato un'espressione del generatore. Ma è ancora difficile da leggere e confuso. fortemente consiglio di farlo invece:

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

Aggiorna : OK, dopo aver apportato queste modifiche, è ancora necessario generare un codice di codifica dei dati dalle bilance. Nella tua definizione di get, utilizzi self.animal, in questo modo:

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

Questo inserisce il valore di ritorno di self.soil.get() in una tupla. Ma poi quel valore è fisso - non cambierà mai. Devi chiamare esplicitamente self.soil.get() ogni volta che desideri il valore aggiornato. Inoltre, le tue comprensioni dell'elenco non accedono mai al valore restituito. Li affetti in questo modo:

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

Ricorda che l'indicizzazione in elenchi e tuple inizia con self.soil.get(), quindi nella tupla 0 sopra, l. Quindi, se vuoi tutto tranne le prime due cose, devi tagliare dall'indice 2:

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

Ma questo ancora non risolve il problema principale, ovvero che devi chiamare l[0] == 'Odocoileous virginiana' per ottenere i dati aggiornati. Un modo per farlo è semplicemente ricreare self.soil.get() ogni volta che viene premuto il pulsante di invio. Sarebbe uno spreco ma funzionerebbe. Un approccio meno dispendioso (ma comunque scomodo) sarebbe salvare la funzione stessa nella tupla, invece del risultato della funzione. Lo faresti così:

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

Nota l'assenza di self.animal dopo (). Ora la tupla non contiene un valore in virgola mobile, ma una funzione che restituisce un valore in virgola mobile. Devi chiamarlo per ottenere il valore, ma restituisce ogni volta il valore completamente aggiornato. Per combinare le funzioni, puoi utilizzare self.soil.get:

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

Ora puoi chiamare lambda per ottenere un valore:

>>> l[2]()
0.30250000000000005

Quindi, per mettere tutto insieme, devi spezzare un po 'di più la comprensione della lista per chiamare esplicitamente l[2], ma una volta fatto questo, dovrebbe funzionare. Questa non è una configurazione ideale, ma temo di dover lasciare la creazione di un'architettura migliorata come esercizio per il lettore.

Altri suggerimenti

A[2][i]/sigma*A[2][i] questo bit sta cercando di indicizzare il float. Dovrebbe essere questo: A[i]/sigma*A[i] invece?

Ho ipotizzato che i valori in A siano tutti in virgola mobile.

La parte for A in A mi sembra un po 'pericolosa.Potrebbe essere sintatticamente corretto, ma di solito è più chiaro usare nomi diversi per le raccolte e gli elementi in quelle raccolte.

Inoltre, for isolates in A: i = A.index(isolates) può essere reso molto più efficace utilizzando for i, isolates in enumerate(A), poiché A.index(isolates) può richiedere molto tempo quando A è grande.

Lo so, non è proprio una risposta alla tua domanda, ma spero che sia comunque utile.

Per rendere più facile il debug (e per aiutarti effettivamente), riscrivi questo:

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

in qualcosa di un po 'più leggibile.Se lo dividi in qualcosa con più righe puoi effettivamente utilizzare un debugger e vedere facilmente quale variabile è un "float" e dove viene indicizzato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top