Existe-t-il une expression génératrice simple qui peut produire des éléments infinis?
C'est une question purement théorique. Pas besoin de réponse "pratique" ici :)
Par exemple, il est facile de créer un générateur fini:
my_gen = (0 for i in xrange(42))
Cependant, pour en créer un infini, j'ai besoin de "polluer" mon espace de noms avec une fonction bidon:
def _my_gen():
while True:
yield 0
my_gen = _my_gen()
Faire des choses dans un fichier séparé et import
plus tard ne compte pas.
Je sais aussi que cela itertools.repeat
fait exactement cela. Je suis curieux de savoir s'il existe une solution à une seule ligne sans cela.
my_gen
, puis faitesmy_gen = my_gen()
.del _my_gen
si vous ne voulez pas confondre les deuxRéponses:
iter
= appelable sans argument + valeur sentinelleint()
revient toujours0
Par conséquent,
iter(int, 1)
est un itérateur infini. Il existe évidemment un grand nombre de variations sur ce thème particulier (surtout une fois que vous l'avez ajoutélambda
au mix). Une variante particulièrement intéressante estiter(f, object())
que l'utilisation d'un objet fraîchement créé comme valeur sentinelle garantit presque un itérateur infini quel que soit l'appelable utilisé comme premier argument.la source
iter
avec des propriétésint
dont nous oublions souvent.itertools.count
:count = lambda start=0, step=1: (start + i*step for i, _ in enumerate(iter(int, 1)))
iter
-fonction est appelée avec deux arguments, il se comporte un peu différent que d' habitude:iter(callable, sentinel) -> iterator
. L'argument 1,callable
est appelé pour chaque itération de l'itérateur, jusqu'à ce qu'il renvoie la valeur desentinel
. Cependant, commeint()
nous le reviendrons toujours0
, nous pouvons appelerint()
pour toujours et ne jamais atteindre 1. Cela produira en fait une liste infinie de0
'sitertools
fournit trois générateurs infinis:count(start=0, step=1)
: 0, 1, 2, 3, 4, ...cycle(p)
: p [0], p [1], ..., p [-1], p [0], ...repeat(x, times=∞)
: x, x, x, x, ...Je n'en connais pas d'autres dans la bibliothèque standard.
Puisque vous avez demandé un monoplace:
la source
∞
symbole pour celui qui se demande - l'omission de l'argument rend la répétition à jamaisiter(int, 1)
incantation. Dommageitertools
qu'il n'y ait pas deendlessly()
méthode dont le seul but est de faire cela;itertools.count()
n'est pas tout à fait lisible non plus.vous pouvez itérer sur un appelable en retournant une constante toujours différente de la sentinelle de iter ()
la source
iter
(ici avec une sentinelle supplémentaire) et la syntaxe delambda
(ici sans paramètres passés, justereturn 0
), le seul endroit à haïr est cet énigmatiqueg1
.Votre système d'exploitation peut fournir quelque chose qui peut être utilisé comme un générateur infini. Par exemple sur Linux
évidemment ce n'est pas aussi efficace que
la source
\n
s apparaissent de temps en temps ... Sournois! :)Aucun qui n'utilise en interne un autre itérateur infini défini comme une classe / fonction / générateur (pas -expression, une fonction avec
yield
). Une expression de générateur s'inspire toujours d'un itérable et ne fait que filtrer et mapper ses éléments. Vous ne pouvez pas passer d'éléments finis à des éléments infinis avec seulementmap
etfilter
, dont vous avez besoinwhile
(ou unfor
qui ne se termine pas, ce qui est exactement ce que nous ne pouvons pas avoir en utilisant uniquementfor
des itérateurs finis).Trivia: PEP 3142 est superficiellement similaire, mais en y regardant de plus près, il semble qu'il nécessite toujours la
for
clause (donc non(0 while True)
pour vous), c'est-à-dire ne fournit qu'un raccourci pouritertools.takewhile
.la source
from itertools import repeat, count, cycle
compte probablement comme "facilement disponible" pour la plupart des gens.iter
. Les itérateurs infinis sont en fait disponibles en tant que intégrés - voir ma réponse :)Assez moche et fou (très drôle cependant), mais vous pouvez construire votre propre itérateur à partir d'une expression en utilisant quelques astuces (sans "polluer" votre espace de noms comme requis):
la source
Vous pourriez peut-être utiliser des décorateurs comme celui-ci par exemple:
Utilisation (1):
Utilisation (2)
Je pense qu'il pourrait être encore amélioré pour se débarrasser de ces moche
()
. Cependant cela dépend de la complexité de la séquence que vous souhaitez pouvoir créer. De manière générale, si votre séquence peut être exprimée à l'aide de fonctions, alors toute la complexité et le sucre syntaxique des générateurs peuvent être cachés à l'intérieur d'un décorateur ou d'une fonction de type décorateur.la source
def
et fermeture? ;)(2^x)
, vous pouvez avoir(x)
. Si vous l'améliorez un peu peut-être aussi fibonacci, etc.seq
wrap