简体   繁体   English

Python:在elif条件下循环

[英]Python: loop in elif condition

I'm running Python 3. 我正在运行Python 3。

Is it possible to put a loop in the condition for elif ? 是否有可能为elif设置循环? Here's the basic idea I'm trying to achieve. 这是我想要实现的基本想法。 The number of items in the list is not constant. 列表中的项目数不是恒定的。

if some_condition:
    do this
elif [ x.method() for x in list ]:
    do this to x
else:
    do something else

Now, this comes to my mind: 现在,我想到了这个:

if some_condition:
    do this
for x in list:
    if x.method():
        do this to x
        break

But I'm trying to avoid running all the if statements, there's a lot of stuff going on in them. 但是我试图避免运行所有的if语句,其中有很多东西正在进行中。 And I would like to get it in the elif part specifically and not in else . 我想特别在elif部分得到它,而不是在else

Edit / more clarification: 编辑/更多说明:

It seems what I would need is any( x.method() for x in list ) but also with a reference to x so that I can then use x if the condition was true. 看起来我需要的是any( x.method() for x in list )但也引用了x这样我就可以在条件为真时使用x

Here's the whole concept I'm trying to get again: 这是我想要再次获得的整个概念:

if condition:
    do this
elif list[0].method():
    do this to list[0]
elif list[1].method():
    do this to list[1]
...
elif list[n].method():
    do this to list[n]
else:
    do this

where method() is some method that returns True or False , and n is the size of the list and not a constant. 其中method()是一些返回TrueFalse方法, n是列表的大小而不是常量。

if [ x.method() for x in list ]:

You ask, is it possible? 你问,有可能吗? Yes. 是。 What does it do, though? 但是它做了什么? Probably not what you intend. 可能不是你想要的。

For the number of items in list , it will fabricate one value in the resulting list. 对于列表中的项目数,它将在结果列表中构造一个值。 For list values, only a list of zero length will be False. 对于列表值,只有零长度的列表将为False。 [False, False, False] is True, so the body of the condition will be executed. [False,False,False]为True,因此将执行条件的主体。

You may be looking for all() or any() if x.method() is supposed to influence the following condition decision. 如果x.method()应该影响以下条件决策,您可能正在寻找all()any()

if all(x.method() for x in list):   # will require that every *x.method* call return truth.

Likewise, you may want 同样,你可能想要

if any(x.method() for x in list):   # only one required. May not do every .method if it can stop early. Beware side-effects.

I don't think what you want -- to have it entirely in the elif -- is possible. 我不认为你想要什么 - 完全在elif - 它是可能的。 You'd have to evaluate whether there is any such value in the list, and then bind it to x in the condition . 您必须评估列表中是否存在any此类值,然后将其绑定到条件中的 x As far as I know, this is not possible in Python's syntax. 据我所知,这在Python的语法中是不可能的。 You can not do an assignment in the condition , and while the loop variable in a list comprehension can "leak" to the outside scope, the same is not true for a generator. 您不能在条件中进行赋值 ,并且虽然列表推导中的循环变量可以 “泄漏”到外部范围,但对于生成器来说却不是这样。

>>> if any(x for x in range(10) if x >= 5):
...     print x
NameError: name 'x' is not defined
>>> if any([x for x in range(10) if x >= 5]):
...     print x
9

In the second case (list), we have a reference to x , but it is the last value from the entire list, and in the first case (generator), x can not be resolved at all. 在第二种情况(列表)中,我们引用了x ,但它是整个列表中的最后一个值,而在第一种情况下(生成器), x根本无法解析。


Instead, here's another variant, using a generator expression to combine the for with the if , and adding an else to the for to enumate your final else clause. 取而代之的是,这里的另一种变体,使用生成表达式组合forif ,并添加elsefor对enumate最终else条款。

if some_condition:
    print "do this"
else:
    for x in (x for x in lst if foo(x)):
        print "do this to", x
        break
    else:
        print "do something else"

I see now. 我现在明白了。 The Pythonic way of doing what your updated edit says is to make a for loop and break out after you find your first item and act on it, and use the almost unknown and unused "else" of a loop. 做出更新编辑所说的Pythonic方法是在找到第一个项目并对其进行操作后进行for循环并突破,并使用循环中几乎未知和未使用的“其他”。

Since the "for / else" idiom is so rarely used, you will need to add a comment about it, for future readers. 由于“for / else”习惯用法很少使用,因此您需要为将来的读者添加关于它的评论。

if some_test:
    first_action()
else:
    for item in list:
        if item.method():
            do_this(item)
            break   # process no more of list
    else:   # for-else only entered if no break from the list!
        final_action()

Read up on loop elses in the Python Tutorial . 阅读Python教程中的循环过程

It is not exactly possible to do what you want, but you can do something similar with list comprehensions: 你不可能做你想做的事情,但是你可以用列表推导做类似的事情:

if some_condition:
    do this
else:
    res = [x for x in list if x.method()]
    if res:
        do something to res[0]
    else:
        do something else

To avoid do x.method() for every value, you could also use itertools.dropwhile . 为避免对每个值执行x.method() ,您还可以使用itertools.dropwhile The following approach will keep checking x.method() until it finds one that is true, then stop and return just that value of x . 以下方法将继续检查x.method()直到找到一个为true,然后停止并返回x值。 If it doesn't find any that are true, it will do something else. 如果它没有找到任何真实的东西,它将做其他事情。

from itertools import dropwhile
if some_condition:
    do this
else:
    try:
        res = next(dropwhile(lambda x: not x.method(), x))
        do something to res
    except StopIteration:
        do something else

This could work as long as you don't need a reference to x outside of the elif block. 只要您不需要在elif块之外引用x,这就可以工作。 This feels closest to the syntax you are asking for, but I would still probably go with either Kevin or Tobias's answers as they are more explicit and readable. 这感觉最接近你要求的语法,但我仍然可能会使用Kevin或Tobias的答案,因为它们更明确和可读。

 def check_and_do(x):
    b = x.method()
    if b:
        do this to x
    return b

if condition:
    do this
elif any(check_and_do(x) for x in list):
    pass  # Already did this to x in check_and_do
else:
    do something else

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM