使用 tkinter Scale 小部件数据列出理解



我正在尝试创建一个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()

感谢许多贡献的改进,这段代码可以工作!

我注意到的第一件事是您将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 开头 - 因此在上面的元组中ll[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],但是一旦您这样做了,这应该可以工作。这不是一个理想的设置,但恐怕我不得不将创建改进的架构作为读者的练习。

A[2][i]/sigma*A[2][i]此位正在尝试索引浮点数。这应该是:A[i]/sigma*A[i]代替吗?

我确实假设 A 中的值都是浮点数。

for A in A部分对我来说似乎有点狡猾。它可能在语法上是相关的,但通常更清楚地为这些集合中的集合和元素使用不同的名称。

此外,for isolates in A: i = A.index(isolates)也可以通过使用for i, isolates in enumerate(A)更有效,因为当A很大时A.index(isolates)可能需要很长时间。

我知道,这不是你问题的答案,但我希望它仍然有用。

为了更容易调试(并实际帮助您(,请重写以下内容:

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

变成更具可读性的东西。如果将其拆分为具有多行的内容,则实际上可以使用调试器,并轻松查看哪个变量是"浮点数"以及它被索引的位置。

最新更新