Понимание списка с помощью виджета tkinter Scale - PullRequest
0 голосов
/ 22 февраля 2012

Я пытаюсь создать модуль Python 2.7 tkinter, который использует данные виджета масштаба, чтобы влиять на понимание списка, который выбирает между животными, чьи вероятностные характеристики представлены в виде списка списков.Модуль сортирует и отображает трех животных в порядке убывания, нажав «Отправить» и активировав соответствующую команду.

В этом примере все три животных находятся на уровне 33% после нажатия «Отправить», поскольку они имеют одинаковые данные вероятности.Животные различаются только среди данных виджета масштаба в столбце 2 списка списков тем, что каждый из них является водным, наземным или обоими.

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

Благодаря множеству улучшений, этот код работает!

Ответы [ 3 ]

0 голосов
/ 22 февраля 2012

Первое, что я заметил, это то, что вы определяете A как пустой словарь, а затем перезаписываете этот пустой словарь с помощью self.animal, который является списком.

    A={}
    A=self.animal

Итак, я 'Я не уверен, что ты собираешься делать здесь.Затем в вашем определении B вы нарезаете его:

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

Это не совпадает с либо определением A, потому что вы не можете нарезать голос, ноначальный индекс, который вы выбрали, - 3, а самый высокий индекс в self.animal - 2.Смешение!Но при более внимательном рассмотрении становится ясно, что проблема в том, что вы повторно используете A в качестве индексной переменной.Вы действительно не должны этого делать;это делает этот код невероятно запутанным.

Это также может привести к ошибкам.Рассмотрим этот код:

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

Как видите, понимание списка заставляет a ссылаться на последнее значение в последовательности, ранее известной как a.Это не происходит в вашем коде, потому что вы использовали выражение генератора.Но это все еще трудно читать и сбивать с толку.Я настоятельно рекомендую сделать это вместо:

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

Обновление : ОК, после внесения этих изменений вам все еще нужно get данные из весов.В вашем определении self.animal вы используете self.soil.get(), например, так:

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

Это возвращает возвращаемое значение self.soil.get() в кортеж.Но тогда это значение фиксируется - оно никогда не изменится.Вы должны явно вызывать self.soil.get() каждый раз, когда вы хотите обновить значение.Кроме того, ваше понимание списка никогда не получит доступ к возвращенному значению.Вы нарезаете их так:

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

Помните, что индексирование в списках и кортежах начинается с 0 - так в приведенном выше кортеже l, l[0] == 'Odocoileous virginiana'.Поэтому, если вы хотите всего, кроме первых двух вещей, вы должны вырезать из индекса 2:

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

Но это по-прежнему не решает проблему с корнем, то есть вы должны вызвать self.soil.get() дляполучить обновленные данные.Один из способов сделать это - просто воссоздать self.animal при каждом нажатии кнопки отправки.Это было бы расточительно, но это сработало бы.Менее расточительный (но все же неловкий) подход заключается в сохранении самой функции в кортеже, а не в результате функции.Вы бы сделали это так:

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

Обратите внимание на отсутствие () после self.soil.get.Теперь кортеж содержит не значение с плавающей запятой, а функцию, которая возвращает значение с плавающей запятой.Вы должны вызвать его, чтобы получить значение, но оно возвращает полностью обновленное значение каждый раз.Чтобы объединить функции, вы можете использовать lambda:

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

Теперь вы можете вызвать l[2], чтобы получить значение:

>>> l[2]()
0.30250000000000005

Итак, чтобы сложить все вместе, у вас естьчтобы немного разбить понимание списка, явно вызвать l[2], но как только вы это сделаете, это должно сработать.Это не идеальная настройка, но, боюсь, мне придется оставить создание улучшенной архитектуры в качестве упражнения для читателя.

0 голосов
/ 22 февраля 2012

Часть for A in A кажется мне немного хитрой. Это может быть синтаксически некорректно, но обычно более понятно использовать разные имена для коллекций и элементов в этих коллекциях.

Также for isolates in A: i = A.index(isolates) можно сделать намного более эффективным с помощью for i, isolates in enumerate(A), так как A.index(isolates) может занять много времени, когда A большое.

Я знаю, на самом деле это не ответ на ваш вопрос, но, тем не менее, надеюсь, что он полезен.

Чтобы упростить отладку (и на самом деле помочь вам), пожалуйста, перепишите это:

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

во что-то более читаемое. Если вы разделите его на несколько строк, вы можете использовать отладчик и легко увидеть, какая переменная является «плавающей точкой» и где она индексируется.

0 голосов
/ 22 февраля 2012

A[2][i]/sigma*A[2][i] этот бит пытается индексировать число с плавающей точкой. Должно ли это быть: A[i]/sigma*A[i] вместо?

Я сделал предположение, что все значения в A являются числами с плавающей запятой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...