Parmi les caractéristiques les plus connues de la programmation fonctionnelle figurent l'évaluation paresseuse et les listes infinies. En Python, ces caractéristiques sont généralement mises en œuvre à l'aide de générateurs. Mais l'un des préceptes de la programmation fonctionnelle est l'immuabilité, et les générateurs ne sont pas immuables. C'est tout le contraire. Chaque fois que l'on appelle next()
sur un générateur, il modifie son état interne.
Une solution de contournement possible consisterait à copier un générateur avant d'appeler next()
sur celui-ci. Cela fonctionne pour certains générateurs tels que count()
. (Peut-être count()
n'est pas générateur ?)
from itertools import count
count_gen = count()
count_gen_copy = copy(count_gen)
print(next(count_gen), next(count_gen), next(count_gen)) # => 0 1 2
print(next(count_gen_copy), next(count_gen_copy), next(count_gen_copy)) # => 0 1 2
Mais si je définis mon propre générateur, par exemple, my_count()
Je ne peux pas le copier.
def my_count(n=0):
while True:
yield n
n += 1
my_count_gen = my_count()
my_count_gen_copy = copy(my_count_gen)
print(next(my_count_gen), next(my_count_gen), next(my_count_gen))
print(next(my_count_gen_copy), next(my_count_gen_copy), next(my_count_gen_copy))
J'obtiens un message d'erreur lorsque j'essaie d'exécuter copy(my_count_gen)
: TypeError: can't pickle generator objects
.
Existe-t-il un moyen de contourner ce problème ou une autre approche ?
Une autre façon de poser la question est peut-être de se demander ce qu'est la copy()
copie quand il copie copy_gen
?
Merci.
P.S. Si j'utilise __iter__()
plutôt que copy()
, le __iter__()
se comporte comme l'original.
my_count_gen = my_count()
my_count_gen_i = my_count_gen.__iter__()
print(next(my_count_gen), next(my_count_gen), next(my_count_gen)) # => 0 1 2
print(next(my_count_gen_i), next(my_count_gen_i), next(my_count_gen_i)) # => 3 4 5