Existe uma expressão geradora direta que pode produzir elementos infinitos?
Esta é uma questão puramente teórica. Não há necessidade de uma resposta "prática" aqui :)
Por exemplo, é fácil fazer um gerador finito:
my_gen = (0 for i in xrange(42))
No entanto, para fazer um infinito, preciso "poluir" meu namespace com uma função falsa:
def _my_gen():
while True:
yield 0
my_gen = _my_gen()
Fazer as coisas em um arquivo separado e fazer import
mais tarde não conta.
Eu também sei que itertools.repeat
faz exatamente isso. Estou curioso para saber se existe uma solução de uma linha sem isso.
python
iterator
generator
infinite-loop
hugomg
fonte
fonte
my_gen
e depois fazermy_gen = my_gen()
.del _my_gen
se não quiser confundir os doisRespostas:
iter
= zero argumento chamável + valor sentinelaint()
sempre retorna0
Portanto,
iter(int, 1)
é um iterador infinito. Obviamente, há um grande número de variações sobre este tema em particular (especialmente quando você adicionalambda
à mistura). Uma variante de nota particular éiter(f, object())
, como usar um objeto recém-criado como o valor sentinela quase garante um iterador infinito, independentemente do chamável usado como o primeiro argumento.fonte
iter
com propriedade daint
qual muitas vezes esquecemos.itertools.count
:count = lambda start=0, step=1: (start + i*step for i, _ in enumerate(iter(int, 1)))
iter
-função é chamado com dois argumentos, ele se comporta um pouco diferente do que normalmente:iter(callable, sentinel) -> iterator
. O argumento 1callable
é chamado para cada iteração do iterador, até que retorne o valor desentinel
. No entanto, comoint()
sempre retornará0
, podemos ligarint()
para sempre e nunca chegar a 1. Isso produzirá uma lista infinita de0
'sitertools
fornece três geradores infinitos: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, ...Não conheço nenhum outro na biblioteca padrão.
Já que você pediu um one-liner:
fonte
∞
símbolo para quem quer saber - omitir o argumento faz repetir rodar para sempreiter(int, 1)
encantamento. Uma penaitertools
não ter umendlessly()
método cujo único propósito é fazer isso;itertools.count()
não é tão legível.você pode iterar sobre um callable retornando uma constante sempre diferente da sentinela de iter ()
fonte
iter
(aqui com sentinela extra) e a sintaxe delambda
(aqui sem nenhum parâmetro passado, apenasreturn 0
), o único lugar para odiar é esse enigmáticog1
.Seu sistema operacional pode fornecer algo que pode ser usado como um gerador infinito. Por exemplo, no Linux
obviamente, isso não é tão eficiente quanto
fonte
\n
aparecerem de vez em quando ... Desonesto! :)Nenhum que não use internamente outro iterador infinito definido como uma classe / função / gerador (não -expressão, uma função com
yield
). Uma expressão geradora sempre extrai de outra iterável e não faz nada além de filtrar e mapear seus itens. Você não pode ir de itens finitos para infinitos com apenasmap
efilter
, você precisawhile
(ou umfor
que não termina, que é exatamente o que não podemos ter usando apenasfor
iteradores e finitos).Curiosidades: PEP 3142 é superficialmente semelhante, mas após uma inspeção mais detalhada, parece que ainda requer a
for
cláusula (portanto, não(0 while True)
para você), ou seja, fornece apenas um atalho paraitertools.takewhile
.fonte
from itertools import repeat, count, cycle
provavelmente conta como "prontamente disponível" para a maioria das pessoas.iter
. Os iteradores infinitos estão realmente disponíveis como embutidos - veja minha resposta :)Bastante feio e louco (muito engraçado no entanto), mas você pode construir seu próprio iterador a partir de uma expressão usando alguns truques (sem "poluir" seu namespace conforme necessário):
fonte
Talvez você possa usar decoradores como este, por exemplo:
Uso (1):
Uso (2)
Acho que poderia ser melhorado para se livrar dessas coisas feias
()
. No entanto, depende da complexidade da sequência que você deseja criar. Falando de maneira geral, se sua sequência pode ser expressa usando funções, então toda a complexidade e açúcar sintático dos geradores podem ser escondidos dentro de um decorador ou de uma função do tipo decorador.fonte
def
e fechamento? ;)(2^x)
, você pode ter(x)
. Se você melhorar um pouco, possivelmente também fibonacci, etc.seq
e recuando o código diretamente parawrap