【问题标题】:Is there a way to do conditionals inside Python (3) for loops?有没有办法在 Python (3) for 循环中执行条件?
【发布时间】:2020-10-22 06:28:15
【问题描述】:

主要来自 Java 编码,想知道 Python 是否可以在其 for 循环中使用条件和不同类型的递增,如 Java 和 C 可以。抱歉,这似乎是一个简单的问题。

即:

boolean flag = True
for(int i = 1; i < 20 && flag; i *= 2) {
    //Code in here
}

【问题讨论】:

  • Python for 循环是基于迭代器的 for 循环,就像 Java for-each 循环一样。如果你想要一个基本的 java / C for 循环,你需要一个 while 循环
  • 可能是this question的副本...无论如何,您确实需要了解可迭代/迭代器才能编写惯用的Python。除了一两个例外,我从来不必使用类似 C 的循环来代替 Python 的基于迭代器的循环结构。使用各种内置库 (itertools) 和非常方便的生成器,几乎不会错过
  • 这能回答你的问题吗? How do I use a C-style for loop in Python?

标签: python python-3.x for-loop


【解决方案1】:

不直接。 for 循环遍历预先生成的序列,而不是生成序列本身。天真的翻译可能看起来像

flag = True
i = 1
while i < 20:
    if not flag:
        break
    ...
    if some_condition:
        flag = False
    i *= 2

但是,您的代码可能可以在将flag 设置为False 的任何位置执行break 语句,因此您可能完全可以摆脱该标志。

i = 1
while i < 20:
    ...
    if some_condition:
        break
    i *= 2

最后,您可以定义自己的生成器进行迭代

def powers_of_two():
    i = 1
    while True:
        yield i
        i *= 2


for i in powers_of_two():
    ...
    if some_condition:
        break
    

【讨论】:

    【解决方案2】:

    Python 中的 for 循环与 C 中的循环不同。它们类似于 Java 7 中应用于迭代的 for-each 循环:

    for (String name: TreeSet<String>(nameList) ) {
       //Your code here
    }
    

    如果您想控制迭代器变量,那么带有breakwhilefor 循环可能是实现这种控制的最简洁的方法。

    这可能是寻找时间编写 Python 理解教程的好时机。尽管它们并不直接适用于您的问题,但这是我最欣赏大约五年前来自 Java 的功能。

    【讨论】:

    • “这可能是寻找时间做 Python 理解教程的好时机。”不,不是!理解结构并不意味着替代 for 循环。
    • @juanpa.arrivillaga 我不是针对这个特殊问题的。我的意思是,它是工具箱中的另一个工具,用于以不同的方式查看数据,以防止陷入这种循环是唯一途径的情况。
    • 我这么说是出于对 Python 标签的经验,那里有大量的问题来自人们试图在列表推导等中作为命令式循环的替代品,并且从根本上不理解这些构造是用于对任意可迭代对象执行声明性映射和过滤操作以构造列表、集合、字典和生成器。我没有投反对票,顺便说一句,我投了赞成票。
    • @juanpa.arrivillaga 我了解,如果您认为不合适,我可以将其删除。大约五年前,从 20 年的 Java 迁移到 Python(我终于克服了空白),看到提供的示例代码是 Java,我想建议探索声明式风格,因为它改变了开发人员看待问题的方式.
    【解决方案3】:

    如果您将步骤设置为某个恒定增量(如 i++、i+=10 等),则可以使用 range()。语法是 -

    range(start,stop,step)
    

    range(start, stop, step) 用作for (int i = start; i &lt; stop; i += step) 的替代品。它不适用于乘法,但如果您有 i &lt; stop &amp;&amp; condition 之类的东西,您仍然可以使用它(使用 break)。

    您提到的那个等效循环可以是 =>

    for(int i=0;i<20;i*=2)  // C/C++ loop
    
    # Python - 1
    i = 0
    while i < 20 :    # Equivalent python loop
        # Code here
        i*=2
    

    如果你愿意使用标志和条件,你必须这样做 =>

    // C/C++
    bool flag = true; 
    for(int i=0;i<20&&flag;i*=2)  // C/C++ loop
    
    # Python - 1
    i,flag = 1,True
    while not flag and i < 20 :    # Equivalent python loop
        # Code here
        i*=2 
    

    希望这会有所帮助!

    【讨论】:

    • 很确定 range(0, 20, 2) 不等价
    • @juanpa.arrivillaga 抱歉,认为 OPasked 增加了 2。现在已更正
    【解决方案4】:

    从某种意义上说,但它并不像 JS 和 Java 那样简单。

    这是您使用 Python 编写的示例,该示例使用带有两个条件的 while 循环。另请注意,在 Python while 循环中,您不能在循环声明中分配或增加索引。

    boolean_flag = True
    
    i = 1
    while (i < 20 and boolean_flag):
        i *= 2
        # Code in here
    

    【讨论】:

      【解决方案5】:

      上面的答案对您的要求很好且有效,但我会给出我的想法。

      max = 20
      for i in range(0, max/2):
          c = i * 2
          if flag:
              #Do work.
              break
      

      或者让它更短:

      max = 20
      for i in range(0, max, 2):
          if flag:
              #Do work.
              break
      

      【讨论】:

        【解决方案6】:

        首先,在 python 中,您不能像在 C++ 或 Java 中那样使用自增运算符进行自增,例如 x++--x。 Python 中的 for 循环适用于 iterator(例如,列表、字符串等)

        Python 循环: for 循环用于迭代序列(即list, a tuple、dictionaryset, or a string`)。

        这不太像其他编程语言中的for 关键字,而更像是其他面向对象编程语言中的迭代器方法。

        使用 for 循环,我们可以执行一组语句,对列表、元组、集合等中的每个项目执行一次。

        示例 打印水果列表中的每个水果:

        fruits = ["apple", "banana", "cherry"]
        for x in fruits:
          print(x)
        

        将打印:

        apple
        banana
        cherry
        

        示例 不要打印香蕉:

        fruits = ["apple", "banana", "cherry"]
        for x in fruits:
          if x == "banana":
            continue
          print(x)
        

        Python 条件:

        在python中,假值的关键字是False,真值的关键字是True

        与 C++ 或 Java 一样,您可以使用 == 来比较值。但与 Java 不同,Java 有严格的类型检查,并且条件需要是 Boolean 语句,在 Python 中:

        1. 如果有某种内容,几乎任何值都会被评估为True
        2. 任何字符串都是True,空字符串除外。
        3. 任何数字都是True,除了0。
        4. 任何listtuplesetdictionary are True`,空的除外。

        实际上,计算结果为False 的值并不多,除了空值,例如 ()、[]、{}、""、数字 0 和值 None。当然,False 的值计算为 False

        以下将返回 False:

        bool(False)
        bool(None)
        bool(0)
        bool("")
        bool(())
        bool([])
        bool({})
        

        在这种情况下,还有一个值或对象的计算结果为 False,也就是说,如果您有一个由具有 __len__ function that returns 0orFalse 的类组成的对象`:

        class myclass():
          def __len__(self):
            return 0
        
        myobj = myclass()
        print(bool(myobj))
        

        【讨论】:

          【解决方案7】:

          您使用 while 表示标志和条件并在循环内递增

          i = 1
          while flag and i < 20:
              # code here
              i = i*2
          

          【讨论】:

            【解决方案8】:

            当然可以,但您可能需要自己做一些事情。

            Python 提供了range() 类,它产生一个可交互的值序列,并带有可选的步长增量。

            for i in range(1, 20, 2):
              # do the things
              # here, i starts at 1, and increments by 2 each loop stops at >= 20
            

            如果你想做更复杂的事情,比如i *= 2,你有两种选择:

            1. 使用 while 循环并自己增加值
            2. 编写一个像range() 这样的自定义生成器来实现这样的事情。

            示例生成器:

            def range_step_mult(start, stop, step):
                while start < stop:
                    yield start
                    start *= step
            
            for i in range_step_mult(1, 100, 2):
                print(i)
            

            请注意此处使用yield 关键字。这对于大范围的性能非常重要,尤其是当可迭代对象位于较大的一侧时。在这里使用关键字可以让 Python 一次简单地处理一个对象,而不是在它开始处理它之前在内存中生成所有这些东西。

            您可以在 for 循环中使用条件,并且可以使用 breakcontinue 关键字在一定程度上控制循环流程。话虽如此,循环是在此块之外生成的,因此您无法更改步骤或中间循环。

            虽然循环是完全不同的故事,但您可以根据需要尽可能多地更改步骤,因为您是第一个递增它的人。

            while 循环示例:

            i = 1
            while i < 100
              if i % 2 == 0:
                i *= 2
              else:
                i += 1
            

            【讨论】:

              【解决方案9】:

              与其他几个答案一样,以下是我实际翻译该代码的方式:

              boolean_flag = True
              i = 1 # actually I wouldn't use i as a variable name, but whatever.
              while i < 20 and boolean_flag:
                  # code goes here
                  i *= 2
              

              我也会考虑使用for 循环,它可能看起来像这样:

              from itertools import takewhile, count
              
              boolean_flag = True
              for i in takewhile(lambda i: i < 20, map(lambda x: 2**x, count())):
                  # code goes here
                  if not boolean_flag:
                      break
              

              但考虑到两者之后,我更喜欢 while 循环。在实践中,我非常 很少需要在这样的循环中定义一个标志。通常,您可以立即从循环中break 检测到会导致您设置标志的条件,或者使用如下逻辑:

              boolean_flag = something()
              something_that_has_to_happen_after_regardless_of_flag_value()
              if not boolean_flag:
                  break
              

              对布尔“break”标志的需求主要是(不完全是)尝试编写所有没有break 的循环的结果,但这样做并没有什么特别的好处。

              也许可以挽救for 循环,或者至少学习一些有关Python 的东西,通过尝试其他方法来编写for 之后的内容。就像lambda i: i &lt; 20 可能是(20).__gt__,但这以它自己的方式令人叹为观止。或者map(lambda 始终是一个警告标志,在这种情况下map(lambda x: 2**x, count()) 可以替换为(2**x for x in count())。或者您可以使用functools.reduce 将幂运算改回乘法,但这不太值得。或者你可以编写一个生成器函数,但这是一个更多样板。

              假设我知道 20 的以 2 为底的对数只能这么大,但我不想让自己成为愚蠢的错误的人质,我可以这样写:

              for i in (2**x for x in range(10)):
                  if not i < 20:
                      break
              

              或者摆脱所有“聪明”的东西:

              for x in range(10):
                  i = 2 ** x
                  if not (i < 20 and boolean_flag):
                      break
              

              但同样,这并不能真正解决 for 循环的基本问题,当您有一个包含正确值的可迭代对象时,在 Python 中您需要将几件事放在一起以提出正确的可迭代对象对于这种情况(特别是如果你想写 20 而不是 20 的对数)。这甚至在你处理旗帜之前。所以,一般来说,当你有一些东西要迭代时,你会使用for 循环,或者很容易 产生一些东西来迭代,然后使用while 循环来进行基于变异本地的更一般的循环变量。

              坦率地说,对于那些具体的数字,你不妨写for i in (1, 2, 4, 8, 16) 并完成它!

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-10-10
                • 2018-03-19
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多