【问题标题】:Incrementing a variable to 100 then deincrementing to 0 and back again in a loop将变量递增到 100 然后递减到 0 并在循环中再次返回
【发布时间】:2017-06-22 18:58:48
【问题描述】:

我只是想知道将变量 x 从 0 一直递增到 100 的最“pythonic”方式是什么,然后当 x 达到 100 时,在循环中递减回 0 然后再回到 100一遍又一遍……

类似这样的:

x = 0
while True:
  if x < 100:
    x += 1
  elif x == 100:
    x -= 1

注意:以上代码已损坏,因此我提出了问题。 :)

执行此操作的最简单方法是什么 - 不一定是最短的代码,也不是寻找单行代码,只是一段非常好的代码。

【问题讨论】:

  • 这不会做你想做的事。 elif x == 100: 会递减到 99,此时if x &lt; 100:True,所以它会再次递增。在尝试优化之前确保某些东西有效更重要。
  • 是的,我意识到上面的代码不起作用。
  • 嗯,你原来的问题没有说明这一点。祝你好运在提供的答案中找到“pythonic”的任何澄清。我会在 pythonicism 之上评价功能(这是一个词吗?)但是你去了。

标签: python loops variables increment


【解决方案1】:

使用两个循环没有什么问题!

while True:
    for x in range(100):
        do_something(x)
    for x in range(98, 0, -1):
        do_something(x)

或者你可以使用一个变量来跟踪你要去的方向:

delta = 1
x = 0
while True:
    do_something(x)
    x += delta
    if x < 1 or x > 99:
        delta = -delta

【讨论】:

    【解决方案2】:

    首先你的代码不起作用:它将计数到 100,然后在 99 和 100 之间交换。所以:1,2,3,..,99,100,99,100,99, ...

    实际上最 Pythonic 的方式可能是根本不递增/递减,而是使用两个ranges:

    while True:
        for x in range(101):
            pass
            #do something with x
        for x in range(99,0,-1):
            pass
            #do something with x
    

    或者用构造一个无限生成器:

    generator = itertools.cycle(itertools.chain(range(101),range(99,0,-1)))
    

    然后您可以将其用作:

    for x in generator:
        pass
        #do something with x
    

    Fr 实例(我这里使用2,因为它使答案更紧凑):

    for x in itertools.cycle(itertools.chain(range(3),range(1,0,-1))):
        print(x)
    

    将产生:

    0
    1
    2
    1
    0
    1
    2
    1
    0
    

    循环将无限重复。

    然而,修复代码的一种方法是添加一个方向,但这可能不是非常Pythonic

    x = 0
    dr = True
    while True:
        if dr:
            x += 1
            if x >= 100:
                dr = False
        else:
            x -= 1
            if x <= 0:
                dr = True
        #do something with x
    

    【讨论】:

    • 很好地呼吁使用两个范围 - 更多的是 Pythonic。
    • 谢谢 - 是的,我喜欢这两个系列。我接受了这个答案,因为它对多种解决方案有很好的解释。
    【解决方案3】:

    试试这个怎么样?

    x = 0
    inc = 1
    while True:
      # do your job here
      if x == 0:
        inc = 1
      elif x == 100:
        inc = -1
      x += inc
    

    【讨论】:

    • 其实我最喜欢这种方法,所以我改了接受的答案。
    【解决方案4】:

    好吧,您当前的解决方案不会完全有效 - 您将递减回 99,然后在 99 和 100 之间循环。

    最简单的可能是添加一个direction 标志,例如:

    x = 0
    isIncreasing = True
    while True:
      if isIncreasing = True:
        x += 1
        if x == 100:
          isIncreasing = False
      else: 
        x -= 1
        if x == 0:
          isIncreasing = True
    

    我有一种更“单行”的方式可以使用 itertools 执行此操作(请参阅上面的帖子),但这将是您当前情况下最“直接”的解决方案。当然,您真正要找的是generator

    【讨论】:

      【解决方案5】:

      我发现单行很简单...那么这个呢:

      Python 2

      from itertools import *
      ups_and_downs = cycle(chain(xrange(100), xrange(100, 0, -1)))
      

      Python 3

      from itertools import *
      ups_and_downs = cycle(chain(range(100), range(100, 0, -1)))
      

      (已编辑以消除一次性错误)

      【讨论】:

      • 请注意,您的范围不是对称的。
      • 你是对的。结果,迭代过早地返回。链接和循环 [0, 100)[100, 0) 应该会更好,看起来也更好;)
      • @jonrsharpe:我认为它们不应该是对称的,否则1000 将被打印两次。
      【解决方案6】:

      既然没有其他人在做,为什么不来点生成器的乐趣呢!

      def lazy_forever_and_ever(hi, lo, start=0, step=1):
          x = start
          vals = {hi: lo, lo: hi}
          target=lo
          while True:
              if x == target:
                  target = vals[target]
              if x >= target:
                  yield x
                  x -= step
              elif x <= target:
                  yield x
                  x += step
      
      if __name__ == '__main__':
          _4eva = lazy_forever_and_ever(0, 10, 0, 1)
          print([next(_4eva) for _ in range(20)])
      
      # output
      [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-15
        • 1970-01-01
        • 2021-09-06
        • 1970-01-01
        • 2014-09-10
        • 2016-01-23
        • 2012-03-14
        • 1970-01-01
        相关资源
        最近更新 更多