【问题标题】:Cycle over list indefinitely无限期循环列表
【发布时间】:2019-03-28 15:47:15
【问题描述】:
a = 1
b = 2
c = 3
x = a

def change_x():
    x = next??
    print("x:", x)

for i in range(10):
    change_x()

如何通过无限期地调用 change_x() 在 a、b、c 之间循环?

输出应该是:

x: 2
x: 3
x: 1
x: 2
...

【问题讨论】:

  • 是否需要变量a、b和c?你可以循环浏览一个列表吗? [1,2,3]
  • 为什么输出从b的值开始,而不是a
  • 大部分答案都指向您正确的工具itertools.cycle,但没有一个真正回答您的问题。将change_x() 函数定义如下:def change_x(c=cycle([a, b, c])): return next(c)
  • @Ashish:是的,变量是必需的,它们是 GUI 中的 tk.StringVars
  • @Sayse:它以 b 开头,因为 print 是在第一次更改之后

标签: python python-3.x list


【解决方案1】:

您可以使用cycle() 并调用next() 多次,以获取循环值。

from itertools import cycle

values = [1, 2, 3]
c = cycle(values)

for _ in range(10):
    print(next(c))

输出:

1
2
3
1
2
3
1
2
3
1

或如@chepner 建议的那样,不使用next()

from itertools import islice

for i in islice(c, 10):
    print(i)

为了得到同样的结果。

【讨论】:

  • 我喜欢这个解决方案,因为您可以利用循环作为生成器,并且可以随心所欲地获得任意数量或数量
  • 其实你甚至不需要显式调用nextfor i in islice(c, 10): print(i).
  • 以匹配 OP 的要求(我如何通过无限期调用 change_x() 在 a、b、c 之间循环?)您可以将其设为函数:def change_x(c=cycle([a, b, c])): return next(c)跨度>
【解决方案2】:

您可以使用itertools.cycle,循环指定abc 中的值:

from itertools import cycle
for i in cycle([a,b,c]):
    print(f'x: {i}')

输出

x: 1
x: 2
x: 0
x: 1
x: 2
x: 0
x: 1
x: 2
x: 0
x: 1
...

【讨论】:

  • @Yatu 拥有无限流对于使用有限但未知长度的序列进行压缩等事情很有用。无论如何,它会给你“足够的”。
  • 我也在考虑具有多个迭代的情况,有些是有限的。对单个可迭代不是很确定,但是是的,这确实是一种有用的情况。感谢您指出@chepner
【解决方案3】:

itertools.cycle 就是这样做的

import itertools,time

for i in itertools.cycle([1,2,3]):
    print(i)
    time.sleep(1)

【讨论】:

    【解决方案4】:

    只需将您的变量放在一个列表中,然后以这种方式选择它们:

    mylist = [a,b,c]
    i=0
    while True:
       print(mylist[i%3])
       i+=1
    

    【讨论】:

      【解决方案5】:

      如果你想手动定义函数,那么你使用yield from

      def cycle(iterables):
          while True:
              yield from iterables
      

      【讨论】:

        【解决方案6】:

        我不确定您是否打算以这种方式使用全局环境变量,但可以按照您使用对象的操作进行操作。

        这假设您知道变量的名称,以便您可以使用globals() 访问这些变量的值。

        class CycleThrough:
            def __init__(self, variable_list = ['a','b','c']):
                self.variable_list = variable_list
                self.current_variable_idx = 0
                self.total_length = len(self.variable_list)
        
            def next_variable(self):
                new_index = self.current_variable_idx + 1
                if new_index == self.total_length:
                    new_index = 0 
        
                self.current_variable_idx = new_index
        
                variable_name = self.variable_list[self.current_variable_idx]
        
        
                global x 
                x = globals()[variable_name]
                print(x)
        
        # defining your variables
        a = 1
        b = 2
        c = 3 
        x = a
        
        #use object method to cycle through and reassign the global variable x
        
        ct = CycleThrough()
        for i in range(10):
            ct.next_variable()
        

        【讨论】:

          【解决方案7】:

          如果您想要一个不使用itertools 的替代方案,您可以创建一个返回您要循环的列表的类,然后在循环中您可以打印该列表,如下面的代码所示:

          class Repeater:
              def __init__(self, l):
                  self.l = l
              def __iter__(self):
                  return self
              def __next__(self):
                  return self.l
          
          l = Repeater([1, 2, 3])
          
          for e in l:
              print(*[f"x: {i}" for i in e], sep='\n')
          

          我假设您使用的是 Python 3.6+,否则,请将 print 语句更改为:

          print(*["x: {}".format(i) for i in e], sep='\n')
          

          输出:

          x: 1
          x: 2
          x: 3
          x: 1
          x: 2
          x: 3
          x: 1
          x: 2
          x: 3
          x: 1
          x: 2
          x: 3
          x: 1
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-05-15
            • 1970-01-01
            • 2017-05-30
            • 1970-01-01
            • 1970-01-01
            • 2016-05-31
            • 1970-01-01
            • 2012-05-01
            相关资源
            最近更新 更多