0

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

由于许多贡献的改进,此代码有效!

4

3 回答 3

0

A[2][i]/sigma*A[2][i] 这个位试图索引浮点数。这应该是:A[i]/sigma*A[i]而不是?

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

于 2012-02-22T17:14:57.130 回答
0

我注意到的第一件事是您定义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都不相符,因为您不能对 dict 进行切片,但您选择的起始索引是3,并且中的最高索引self.animal2。令人困惑!但仔细观察,很明显问题在于您正在重用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)

注意没有()after 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],但是一旦您这样做了,这应该可以工作。这不是一个理想的设置,但恐怕我不得不将创建改进的架构作为读者的练习。

于 2012-02-22T17:19:08.407 回答
0

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]

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

于 2012-02-22T17:19:18.227 回答