Python If / Elif / Else,For和Lists

时间:2017-06-24 10:17:11

标签: python list for-loop if-statement

我试图在列表上使用else语句迭代elif语句。这是我的代码:

    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)

meal_objects,build_meal_objects和ingredient_objects是列表。

问题是这个代码很可怕有很多原因。如果不满足第一个条件,即使其中一个for循环条件已经运行,每个for循环也会运行,并且最后的else语句也将运行。实际上,如果满足任何for循环中的任何if语句,那么if块的其余部分就不应该执行。

代码应该更像是这个伪代码:

    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)

我觉得我可能会忽略一些非常简单的事情,所以请原谅我,如果是这样,或者这是一个写得不好的问题。谢谢!

4 个答案:

答案 0 :(得分:1)

可能最简单(也是最灵活的方法)是将它们放在一个函数中并强制return,例如:

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)

然后将其称为:

lst, item = f(clickPoint, meal_objects, build_meal_objects, ingredient_objects)

这意味着只有所有列表中的第一个元素都有一个填充集,它会返回对列表的引用以及设置的项目,如果要进行打印,可以稍后检查。

例如:

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所具有的for/else语法,但这要求你有效地将序列链接到一个for来发出{{} 1}} on,例如:

break

答案 1 :(得分:1)

好的,这需要一些解释。请看下面的内容。

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)

上述程序只会打印值,直到找到3

输出:

0
0
0
0
0
0
1
2
3

如果最后continueelse不存在会怎样?

for x in range(5):
    for y in range(5):
        print (x*y)
        if x*y==3:
            break

输出:

0
0
0
0
0
0
1
2
3
0
2
4
6
8
0
3
0
4
8
12
16

在找到3之后看到它甚至没有停止,因为break仅导致退出内循环。因此,第一个代码可用于退出嵌套循环。即使是非常深层次的嵌套循环。

那么如何在代码中应用它?看看这个!

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)

使用标志变量。现在在上面的代码中首先设置flag1=Trueflag2=True。第一个if块被执行,如果clickPoint为None,则打印出来。并且 flag2设置为False

为什么我这样做?确保在下一个if语句中失败。因此,没有任何for循环被执行。

如果clickPoint不是None,则下一部分。下一个if已执行,请注意这里我做了一些小改动!

my_objects = {0: meal_objects, 1: build_meal_objects, 2: ingredient_objects}

创建dict个对象,然后使用range(your_dict_size)逐个获取。 注意这样您就可以添加越来越多的对象。

记得我解释了退出嵌套循环的问题?这正是发生的事情。你得到你想要的那一刻就是它控制退出而不再运行循环。

并将 flag1 设置为False

注意:两个标志变量的原因是为了确保您的else部分(此处为最后if)始终执行如果前两个if失败。

答案 2 :(得分:0)

我认为这是你正在尝试做的事情:

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循环调用each._button.setFill('green')。如果没有人调用它,那么print语句就会运行。

答案 3 :(得分:0)

好像你可能会使用itertools.chain将for循环压缩到一个块中。这样你就可以循环遍历列表中的所有项目,并在到达第一个“内部”的项目时立即停止。

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)