Je dois parcourir une liste circulaire, éventuellement plusieurs fois, en commençant par le dernier élément visité.
Le cas d'utilisation est un pool de connexion. Un client demande la connexion, un itérateur vérifie si la connexion pointée est disponible et la renvoie, sinon elle boucle jusqu'à en trouver une disponible.
Existe-t-il un moyen pratique de le faire en Python?
Utilisez itertools.cycle
, c'est son but exact:
from itertools import cycle
lst = ['a', 'b', 'c']
pool = cycle(lst)
for item in pool:
print item,
Sortie:
a b c a b c ...
(Boucles pour toujours, évidemment)
Pour faire avancer manuellement l'itérateur et en extraire les valeurs une par une, appelez simplement next(pool)
:
>>> next(pool)
'a'
>>> next(pool)
'b'
La bonne réponse est d'utiliser itertools.cycle . Mais supposons que cette fonction de bibliothèque n'existe pas. Comment le mettriez-vous en œuvre?
Utilisez un générateur :
def circular():
while True:
for connection in ['a', 'b', 'c']:
yield connection
Ensuite, vous pouvez soit utiliser une instruction for
pour itérer indéfiniment, soit appeler next()
pour obtenir la valeur unique suivante de l'itérateur du générateur:
connections = circular()
next(connections) # 'a'
next(connections) # 'b'
next(connections) # 'c'
next(connections) # 'a'
next(connections) # 'b'
next(connections) # 'c'
next(connections) # 'a'
#....
Ou vous pouvez faire comme ça:
conn = ['a', 'b', 'c', 'c', 'e', 'f']
conn_len = len(conn)
index = 0
while True:
print(conn[index])
index = (index + 1) % conn_len
imprime a b c d e f a b c ... pour toujours
vous pouvez accomplir ceci avec la boucle append(pop())
:
l = ['a','b','c','d']
while 1:
print l[0]
l.append(l.pop(0))
ou for i in range()
boucle:
l = ['a','b','c','d']
ll = len(l)
while 1:
for i in range(ll):
print l[i]
ou simplement:
l = ['a','b','c','d']
while 1:
for i in l:
print i
qui impriment tous:
>>>
a
b
c
d
a
b
c
d
...etc.
des trois, je serais sujet à l'approche append (pop ()) en tant que fonction
servers = ['a','b','c','d']
def rotate_servers(servers):
servers.append(servers.pop(0))
return servers
while 1:
servers = rotate_servers(servers)
print servers[0]
Si vous souhaitez utiliser n
fois, implémentez la ncycles
recette d'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']
Vous avez besoin d'un itérateur personnalisé - Je vais adapter l'itérateur de cette réponse .
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