Python 中的循环列表迭代器

我需要在一个循环列表中迭代,可能需要多次迭代,每次迭代都从最后访问的项目开始。

用例是一个连接池。客户机请求连接,迭代器检查指向的连接是否可用并返回它,否则循环直到找到可用的连接。

如何在 Python 中巧妙地实现这一点?


如果您需要立即创建一个长度达到一定长度的结果列表,而不是根据需要进行迭代: 参见 重复列表到最大元素数了解一般技术,参见 如何复制数组到特定长度的数组了解特定于 Numpy 的技术。

95192 次浏览

正确的答案是使用 Itertools.Cycle。但是,让我们假设库函数不存在。您将如何实现它?

使用 发电机:

def circular():
while True:
for connection in ['a', 'b', 'c']:
yield connection

然后,您可以使用 for语句进行无限次迭代,或者您可以调用 next()从生成器迭代器中获取下一个值:

connections = circular()
next(connections) # 'a'
next(connections) # 'b'
next(connections) # 'c'
next(connections) # 'a'
next(connections) # 'b'
next(connections) # 'c'
next(connections) # 'a'
#....

使用 itertools.cycle,这就是它的确切用途:

from itertools import cycle


lst = ['a', 'b', 'c']


pool = cycle(lst)


for item in pool:
print item,

产出:

a b c a b c ...

(循环永远,显然)


为了手动推进迭代器并逐个从中提取值,只需调用 next(pool):

>>> next(pool)
'a'
>>> next(pool)
'b'

您需要一个自定义迭代器——我将改编 这个答案中的迭代器。

from itertools import cycle


class ConnectionPool():
def __init__(self, ...):
# whatever is appropriate here to initilize
# your data
self.pool = cycle([blah, blah, etc])
def __iter__(self):
return self
def __next__(self):
for connection in self.pool:
if connection.is_available:  # or however you spell it
return connection

或者你可以这样做:

conn = ['a', 'b', 'c', 'd', 'e', 'f']
conn_len = len(conn)
index = 0
while True:
print(conn[index])
index = (index + 1) % conn_len

永远打印出来

你可以通过 append(pop())循环来完成:

l = ['a','b','c','d']
while True:
print l[0]
l.append(l.pop(0))

for i in range()循环:

l = ['a','b','c','d']
ll = len(l)
while True:
for i in range(ll):
print l[i]

或者简单地说:

l = ['a','b','c','d']


while True:
for i in l:
print i

所有这些印刷品:

>>>
a
b
c
d
a
b
c
d
...etc.

在这三种方法中,我倾向于使用附加(pop ())方法作为函数

servers = ['a','b','c','d']


def rotate_servers(servers):
servers.append(servers.pop(0))
return servers


while True:
servers = rotate_servers(servers)
print servers[0]

如果你想循环 n次,实现 ncycles Itertools 食谱:

from itertools import chain, repeat




def ncycles(iterable, n):
"Returns the sequence elements n times"
return chain.from_iterable(repeat(tuple(iterable), n))




list(ncycles(["a", "b", "c"], 3))
# ['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c']

为了避免无限循环,我使用数组的长度来迭代,直到列表的大小加倍。您可以实现自己的前置条件。避免无限循环。

#Implement Circular Linked List
from itertools import cycle
list=[1,2,3,4,5]
lstlength=len(list)*2
print(lstlength)
pool=cycle(list)
i=0
#To avoid infinite loop break when you have iterated twice size of the list
for items in pool:
print(items)
if i >lstlength:
break
i += 1
class A(object):
def __init__(self, l):
self.strt = 0
self.end = len(l)
self.d = l


def __iter__(self):
return self


def __next__(self):
val = None
if self.strt>=self.end:
self.strt=0
val = self.d[self.strt]
self.strt += 1
return val


a= A([8,9,7,66])
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))