如果索引> len(list),如何按索引循环遍历列表并从头开始?

ves*_*and 0 python

精华:

对于像 的列表['A', 'B', 'C'],我试图构建或找到一个函数,该函数将在每次调用时返回列表的下一个元素。在这种情况下,如果它被调用超过 3 次,A则将被返回。在那之后B等等。


详细信息和我尝试过的内容:

我有一个['A', 'B', 'C']要应用于不同对象的颜色列表。每次运行代码时,对象的数量可能会有所不同。如果列表中的对象多于颜色,我希望第四个对象具有 color 'A'。所以,正如标题所说,我想遍历一个列表 by 和 index 并从头开始 if index > len(list)。以下自定义函数looper将做到这一点。

def looper(lst, runs):
    j = 0
    for i in range(0, (len(lst)+(runs-(len(lst))))):
        if i < len(lst):
            print(lst[i])
        else:
            print(lst[j])
            j +=1
Run Code Online (Sandbox Code Playgroud)

测试 1

# input:
runs = 2
looper(['A', 'B', 'C'], runs)

# output:
A
B
Run Code Online (Sandbox Code Playgroud)

测试 2

#input :
runs = 5
looper(['A', 'B', 'C'], runs)

#output :
A
B
C
A
B
Run Code Online (Sandbox Code Playgroud)

如您所见,这个简单的函数如果runs变得足够大就会崩溃。此外,每次调用此函数时,我都想从上次调用结束的索引处开始。所以,从上一个例子开始,下次调用它时:

runs = 1
looper(['A', 'B', 'C'], runs)
Run Code Online (Sandbox Code Playgroud)

那么输出将是:

c
Run Code Online (Sandbox Code Playgroud)

我还没有完全了解生成器的使用,我只能猜测这将是一个有用的方法。但是我拿起你应该只使用一台发电机,如果你想在一个列表喜欢循环一次,按在岗顶端回答生成器表达式与列表理解。所以据我所知,生成器毕竟没有用,因为在 Python 中重置生成器对象似乎有点复杂。感谢您的任何建议!

Tom*_*koo 5

结合评论中的建议,您可以实现您正在寻找的确切行为。我不会详细介绍生成器的工作原理,因为您从有经验的人那里得到了更简洁的答案。我总结一下,生成器的要点是,只有当您要求时,它们才会yield为您提供下一个元素。生成器和 Python 中的其他任何东西一样都是对象,所以只要您共享同一个生成器对象,您将始终拥有最后一个元素的书签yielded。现在用代码更好地理解:

首先,我们将概括该looper函数:

def looper(iterable, runs):
    i = cycle(iterable)
    for _ in range(runs):
        print(next(i))
    return i
Run Code Online (Sandbox Code Playgroud)

因此,现在它允许您runs在任何可迭代对象上使用任意数量的函数调用一次该函数。另一方面,如果您打算多次调用它,它会返回为重用而创建的生成器。

现在让我们测试一些情况:

a = [1, 2, 3]

looper(a, 6)
Run Code Online (Sandbox Code Playgroud)

这将打印:

1
2
3
1
2
3
Run Code Online (Sandbox Code Playgroud)

但更重要的是,这还将:

i = looper(a, 2)
looper(i, 2)
looper(i, 2)
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 我们之所以能够做到这一切,itertools.cycle是因为它返回了一个生成器对象。

  • 如果您想要调用之间的循环效果,则必须将返回的生成器传递给后续调用。例如,如果我们尝试做looper(a, 2)几次,我们总是会得到:

      1
      2
    
    Run Code Online (Sandbox Code Playgroud)

    这是因为每次我们调用该函数时,我们都会cycle再次调用并从从第一个元素开始的原始列表中创建一个新的生成器

  • 另一方面,当将生成器传递给函数时,该cycle函数将创建一个新的生成器,但从前一个生成器停止。这样,如果您继续传递第一个返回的cycle生成器,则可以保留循环效果。