Is there an expression for an infinite generator?

2019-01-04 08:47发布

Is there a straight-forward generator expression that can yield infinite elements?

This is a purely theoretical question. No need for a "practical" answer here :)


For example, it is easy to make a finite generator:

my_gen = (0 for i in xrange(42))

However, to make an infinite one I need to "pollute" my namespace with a bogus function:

def _my_gen():
    while True:
        yield 0
my_gen = _my_gen()

Doing things in a separate file and import-ing later doesn't count.


I also know that itertools.repeat does exactly this. I'm curious if there is a one-liner solution without that.

8条回答
\"骚年 ilove
2楼-- · 2019-01-04 09:30

None that doesn't internally use another infinite iterator defined as a class/function/generator (not -expression, a function with yield). A generator expression always draws from anoter iterable and does nothing but filtering and mapping its items. You can't go from finite items to infinite ones with only map and filter, you need while (or a for that doesn't terminate, which is exactly what we can't have using only for and finite iterators).

Trivia: PEP 3142 is superficially similar, but upon closer inspection it seems that it still requires the for clause (so no (0 while True) for you), i.e. only provides a shortcut for itertools.takewhile.

查看更多
Fickle 薄情
3楼-- · 2019-01-04 09:33

Quite ugly and crazy (very funny however), but you can build your own iterator from an expression by using some tricks (without "polluting" your namespace as required):

{ print("Hello world") for _ in
    (lambda o: setattr(o, '__iter__', lambda x:x)
            or setattr(o, '__next__', lambda x:True)
            or o)
    (type("EvilIterator", (object,), {}))() } 
查看更多
爷、活的狠高调
4楼-- · 2019-01-04 09:35

you can iterate over a callable returning a constant always different than iter()'s sentinel

g1=iter(lambda:0,1)
查看更多
SAY GOODBYE
5楼-- · 2019-01-04 09:36
for x in iter(int, 1): pass
  • Two-argument iter = zero-argument callable + sentinel value
  • int() always returns 0

Therefore, iter(int, 1) is an infinite iterator. There are obviously a huge number of variations on this particular theme (especially once you add lambda into the mix). One variant of particular note is iter(f, object()), as using a freshly created object as the sentinel value almost guarantees an infinite iterator regardless of the callable used as the first argument.

查看更多
老娘就宠你
6楼-- · 2019-01-04 09:39

(as some mentioned, thanks to python documentation https://docs.python.org/2/library/itertools.html#itertools.cycle)

def iter_cycle(iterator):
    saved = []
    for iterable in iterator:
        yield iterable
        saved.append(iterable)
    while saved:
        for element in saved:
              yield element

a = iter_cycle(iter([1,2,3]))

next(a) -> 1 next(a) -> 2 next(a) -> 3

next(a) -> 1

查看更多
Animai°情兽
7楼-- · 2019-01-04 09:42

Your OS may provide something that can be used as an infinite generator. Eg on linux

for i in (0 for x in open('/dev/urandom')):
    print i

obviously this is not as efficient as

for i in __import__('itertools').repeat(0)
    print i
查看更多
登录 后发表回答