قائمة الفهم مع بيانات القطعة tkinter Scale
-
29-10-2019 - |
سؤال
أحاول إنشاء وحدة 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
- هكذا في الصف أعلاه 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]
, ، ولكن بمجرد القيام بذلك، من المفترض أن ينجح هذا الأمر.هذا ليس إعدادًا مثاليًا، ولكن أخشى أنني يجب أن أترك إنشاء بنية محسنة كتمرين للقارئ.
نصائح أخرى
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.index(isolates)
يمكن أن يستغرق وقتًا طويلاً عندما يكون A كبيرًا.
أعلم أن هذا ليس إجابة لسؤالك حقًا، ولكن آمل أن يكون مفيدًا مع ذلك.
لتسهيل تصحيح الأخطاء (ولمساعدتك فعليًا)، يرجى إعادة كتابة هذا:
[(A[0], "%.2f" % (reduce(mul,A[3:])*A[2][i]/sigma*A[2][i])) for A in A]
إلى شيء أكثر قابلية للقراءة.إذا قمت بتقسيمه إلى شيء يحتوي على أسطر متعددة، فيمكنك بالفعل استخدام مصحح الأخطاء، ورؤية المتغير "العائم" بسهولة ومكان فهرسته.