Pregunta

Estoy tratando de crear un módulo tkinter de Python 2.7 que usa datos de widget de escala para influir en la comprensión de una lista que selecciona entre animales cuyos rasgos de probabilidad se representan como una lista de listas.El módulo ordena y muestra los tres animales en orden descendente al hacer clic en 'Enviar' y activar el comando asociado.

En este ejemplo, los tres animales están al 33% después de hacer clic en "Enviar" porque comparten los mismos datos de probabilidad.Los animales solo difieren entre los datos del widget de escala en la columna 2 de la lista de listas en que cada uno es acuático, terrestre o ambos.

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

¡Gracias a las muchas mejoras aportadas, este código funciona!

¿Fue útil?

Solución

Lo primero que noto es que define A como un diccionario vacío y luego sobrescribe ese diccionario vacío con self.animal, que es una lista.

    A={}
    A=self.animal

Así que no estoy seguro de lo que pretendes hacer aquí. Luego, en su definición de B, lo divide:

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

Esto no cuadra con la definición de tampoco de A, porque no puede dividir un dict, pero el índice inicial que eligió es 3, y el índice más alto en self.animal es 2. ¡Confuso! Pero mirando más de cerca, queda claro que el problema es que está reutilizando A como una variable de indexación. Realmente no debería hacer eso; hace que este código sea increíblemente confuso.

También puede provocar errores. Considere este código:

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

Como puede ver, la comprensión de la lista hace que a se refiera al último valor de la secuencia anteriormente conocida como a. Esto no sucede en su código porque utilizó una expresión generadora. Pero sigue siendo difícil de leer y confuso. Recomiendo encarecidamente hacer esto en su lugar:

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

Actualización: de acuerdo, después de realizar esos cambios, aún necesita generar codificar y codificar los datos de las escalas. En su definición de get, usa self.animal, así:

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

Esto coloca el valor de retorno de self.soil.get() en una tupla. Pero luego ese valor es fijo, nunca cambiará. Debe llamar explícitamente a self.soil.get() cada vez que desee el valor actualizado. Además, las comprensiones de su lista nunca acceden al valor devuelto allí. Los rebana así:

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

Recuerde que la indexación en listas y tuplas comienza con self.soil.get(), por lo que en la tupla anterior 0, l. Entonces, si quiere todo menos las dos primeras cosas, debe dividir el índice 2:

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

Pero esto aún no resuelve el problema raíz, que es que debe llamar a l[0] == 'Odocoileous virginiana' para obtener los datos actualizados. Una forma de hacerlo es simplemente recreando self.soil.get() cada vez que se presiona el botón Enviar. Eso sería un desperdicio, pero funcionaría. Un enfoque menos derrochador (pero aún incómodo) sería guardar la función en sí en la tupla, en lugar del resultado de la función. Lo harías así:

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

Tenga en cuenta la ausencia de self.animal después de (). Ahora la tupla no contiene un valor de punto flotante, sino una función que devuelve un valor de punto flotante. Tienes que llamarlo para obtener el valor, pero siempre devuelve el valor completamente actualizado. Para combinar funciones, puede utilizar self.soil.get:

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

Ahora puede llamar a lambda para obtener un valor:

>>> l[2]()
0.30250000000000005

Entonces, para ponerlo todo junto, debes dividir un poco más la comprensión de la lista para llamar explícitamente a l[2], pero una vez que hayas hecho eso, esto debería funcionar. Esta no es una configuración ideal, pero me temo que debo dejar la creación de una arquitectura mejorada como un ejercicio para el lector.

Otros consejos

A[2][i]/sigma*A[2][i] este bit está intentando indexar el flotador. ¿Debería ser: A[i]/sigma*A[i] en su lugar?

Supuse que los valores en A son todos flotantes.

La parte de for A in A me parece un poco dudosa.Puede ser sintácticamente correcto, pero generalmente es más claro usar diferentes nombres para colecciones y elementos en esas colecciones.

También for isolates in A: i = A.index(isolates) se puede hacer mucho más efectivo usando for i, isolates in enumerate(A), ya que A.index(isolates) puede llevar mucho tiempo cuando A es grande.

Lo sé, no es realmente una respuesta a tu pregunta, pero espero que sea útil de todos modos.

Para facilitar la depuración (y realmente ayudarlo), vuelva a escribir esto:

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

en algo un poco más legible.Si lo divide en algo con varias líneas, puede usar un depurador y ver fácilmente qué variable es un 'flotante' y dónde se indexa.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top