Pergunta

Estou tentando criar um módulo python 2.7 tkinter que usa dados de widget de escala para influenciar uma compreensão de lista que seleciona entre animais cujas características de probabilidade são representadas como uma lista de listas.O módulo classifica e exibe os três animais em ordem decrescente ao clicar em 'Enviar' e ativar o comando associado.

Neste exemplo, todos os três animais estão em 33% depois de clicar em 'Enviar' porque eles compartilham os mesmos dados de probabilidade.Os animais diferem apenas entre os dados do widget de escala na coluna 2 da lista de listas em que cada um é aquático, terrestre ou 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()

Graças a muitas melhorias contribuídas, este código funciona!

Foi útil?

Solução

A primeira coisa que noto é que você define A como um dicionário vazio e, em seguida, substitui esse dicionário vazio por self.animal, que é uma lista.

    A={}
    A=self.animal

Portanto, não tenho certeza do que você pretende fazer aqui. Então, em sua definição de B, você o divide:

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

Isso não se enquadra com tampouco a definição de A, porque você não pode fatiar um dicionário, mas o índice inicial que você escolheu é 3, e o índice mais alto em self.animal é 2. Confuso! Mas olhando mais de perto, fica claro que o problema é que você está reutilizando A como uma variável de indexação. Você realmente não deveria fazer isso; isso torna este código incrivelmente confuso.

Também pode causar erros. 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 você pode ver, a compreensão da lista faz com que a se refira ao último valor na sequência anteriormente conhecida como a. Isso não acontece em seu código porque você usou uma expressão geradora. Mas ainda é difícil de ler e confuso. Eu fortemente recomendo fazer isso em vez disso:

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

Atualizar : OK, depois de fazer essas alterações, você ainda precisa get os dados das balanças. Em sua definição de self.animal, você usa self.soil.get(), assim:

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

Isso coloca o valor de retorno de self.soil.get() em uma tupla. Mas então esse valor é fixo - ele nunca mudará. Você deve chamar explicitamente self.soil.get() toda vez que quiser o valor atualizado. Além disso, suas compreensões de lista nunca acessam o valor retornado lá. Você os corta assim:

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

Lembre-se de que a indexação em listas e tuplas começa com 0 - portanto, na tupla acima l, l[0] == 'Odocoileous virginiana'. Portanto, se você quiser tudo, menos as duas primeiras coisas, terá que cortar do índice 2:

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

Mas isso ainda não resolve o problema raiz, que é que você deve chamar self.soil.get() para obter os dados atualizados. Uma maneira de fazer isso é simplesmente recriando self.animal toda vez que o botão enviar é pressionado. Isso seria um desperdício, mas funcionaria. Uma abordagem menos desperdiçadora (mas ainda estranha) seria salvar a própria função na tupla, em vez do resultado da função. Você faria isso assim:

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

Observe a ausência de () após self.soil.get. Agora, a tupla contém não um valor de ponto flutuante, mas uma função que retorna um valor de ponto flutuante. Você precisa chamá-lo para obter o valor, mas ele sempre retorna o valor totalmente atualizado. Para combinar funções, você pode usar lambda:

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

Agora você pode chamar l[2] para obter um valor:

>>> l[2]()
0.30250000000000005

Então, para colocar tudo junto, você tem que quebrar a compreensão da lista um pouco mais para chamar explicitamente l[2], mas depois de fazer isso, deve funcionar. Esta não é uma configuração ideal, mas tenho que deixar a criação de uma arquitetura aprimorada como um exercício para o leitor.

Outras dicas

A[2][i]/sigma*A[2][i] este bit está tentando indexar o float. Em vez disso, deveria ser: A[i]/sigma*A[i]?

Eu presumi que os valores em A são todos flutuantes.

A parte for A in A parece um pouco duvidosa para mim.Pode ser sintaticamente correto, mas geralmente é mais claro usar nomes diferentes para coleções e elementos nessas coleções.

Além disso, for isolates in A: i = A.index(isolates) pode ser muito mais eficaz usando for i, isolates in enumerate(A), pois A.index(isolates) pode demorar muito quando A é grande.

Eu sei, não é exatamente uma resposta à sua pergunta, mas espero que seja útil mesmo assim.

Para facilitar a depuração (e realmente ajudá-lo), reescreva isto:

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

em algo um pouco mais legível.Se você dividi-lo em algo com várias linhas, você pode realmente usar um depurador e ver facilmente qual variável é um 'float' e onde está sendo indexada.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top