Python If/Elif/Else, For and Lists
我尝试在列表上迭代elif语句,并在末尾使用else语句。这是我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | if clickPoint is None: print(clickPoint) for each in meal_objects: if inside(clickPoint, each._button): each._button.setFill('green') break for each in build_meal_objects: if inside(clickPoint, each._button): each._button.setFill('green') break for each in ingredient_objects: if inside(clickPoint, each._button): each._button.setFill('green') break else: print(clickPoint) |
食物对象、构建食物对象和成分对象都是列表。
问题是,由于许多原因,这个代码是可怕的。如果不满足第一个条件,则每个for循环都将运行,即使其中一个for循环条件已经运行,并且最终的else语句也将运行。实际上,如果满足任何for循环中的任何if语句,则不应执行其余的if块。
代码应该更像这个伪代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | if clickPoint is None: print(clickPoint) elif for each in meal_objects: if inside(clickPoint, each._button): each._button.setFill('green') break elif for each in build_meal_objects: if inside(clickPoint, each._button): each._button.setFill('green') break elif for each in ingredient_objects: if inside(clickPoint, each._button): each._button.setFill('green') break else: print(clickPoint) |
我觉得我可能忽略了一些非常简单的事情,所以如果是这样,或者这是一个写得不好的问题,请原谅我。谢谢!
好吧,这需要一些解释。看看下面这个。
1 2 3 4 5 6 7 8 | for x in range(5): for y in range(5): print (x*y) if x*y==3: break else: continue # executed if the loop finished normally (no break) break # executed if 'continue' was skipped (break) |
上面的程序只打印值,直到找到一个
输出:
1 2 3 4 5 6 7 8 9 | 0 0 0 0 0 0 1 2 3 |
如果最后一个
1 2 3 4 5 | for x in range(5): for y in range(5): print (x*y) if x*y==3: break |
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 0 0 0 0 0 0 1 2 3 0 2 4 6 8 0 3 0 4 8 12 16 |
看,它甚至在找到一个
那么如何在代码中应用它呢?看这个!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | my_objects = {0: meal_objects, 1: build_meal_objects, 2: ingredient_objects} flag2=True flag1=True if clickPoint is None: print(clickPoint) flag2=False if flag2: for i in range(3): temp_obj = my_objects[i] for each in temp_obj: if inside(clickPoint, each._button): each._button.setFill('green') flag1=False break else: continue break if flag1 and flag2: print(clickPoint) |
使用标志变量。现在在上面的代码中,首先设置了
我为什么要这么做?以确保它在下一个
下一部分,如果以东十一〔13〕不是以东十一〔18〕的话。下一个
1 | my_objects = {0: meal_objects, 1: build_meal_objects, 2: ingredient_objects} |
创建一个
还记得我解释过退出嵌套循环吗?事情就是这样。一旦你得到你想要的,那就是控制出口,不再运行for循环。
并将flag1设置为
注:两个标志变量的原因是为了确保在前两个
可能最简单(也是最灵活的方法)是将它们放入函数中并强制执行
1 2 3 4 5 6 7 8 9 10 | def f(clickPoint, *lists): if clickPoint is None: # or raise an exception instead as seems more an exception than natural return (None, None) for lst in lists: for item in lst: if inside(clickPoint, item._button): item._button.setFill('green') return (lst, item) return (None, None) |
然后称之为:
1 | lst, item = f(clickPoint, meal_objects, build_meal_objects, ingredient_objects) |
这意味着只有所有列表的第一个元素将有一个填充集,它返回对列表和已设置项的引用,如果您想进行打印,可以稍后检查。
如:
1 2 3 4 | if (lst, item) == (None, None): # handle that nothing was set? else: # you know which button (`item`) in which list (`lst`) had its fill changed |
我想如果您真的有必要,您可以使用Python的
1 2 3 4 5 6 | for lst, item in ((lst, item) for lst in (meal_objects, build_meal_objects, ingredient_objects) for item in lst): if inside(clickPoint, item._button): item._button.setFill('green') break else: # this only enters if `break` was NOT issued in the for-loop print('nothing set') |
似乎您可以很好地使用
1 2 3 4 5 6 7 8 9 10 | from itertools import chain if clickPoint is None: print(clickPoint) for each in chain(meal_objects, build_meal_objects, ingredient_objects): if inside(clickPoint, each._button): each._button.setFill('green') break else: print(clickPoint) |
我想这就是你想做的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | if clickPoint is None: print(clickPoint) else: called = False for each in meal_objects: if inside(clickPoint, each._button): each._button.setFill('green') called = True break if not called: for each in build_meal_objects: if inside(clickPoint, each._button): each._button.setFill('green') called = True break if not called: for each in ingredient_objects: if inside(clickPoint, each._button): each._button.setFill('green') called = True break if not called: print(clickPoint) |
这确保只有一个for循环调用