Is there an expression for an infinite generator?

守給你的承諾、 提交于 2019-12-17 03:27:13

问题


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.


回答1:


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.




回答2:


itertools provides three infinite generators:

  • 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, ...

I don't know of any others in the standard library.


Since you asked for a one-liner:

__import__("itertools").count()



回答3:


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

g1=iter(lambda:0,1)



回答4:


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



回答5:


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.




回答6:


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,), {}))() } 



回答7:


Maybe you could use decorators like this for example:

def generator(first):
    def wrap(func):
        def seq():
            x = first
            while True:
                yield x
                x = func(x)
        return seq
    return wrap

Usage (1):

@generator(0)
def blah(x):
    return x + 1

for i in blah():
    print i

Usage (2)

for i in generator(0)(lambda x: x + 1)():
    print i

I think it could be further improved to get rid of those ugly (). However it depends on the complexity of the sequence that you wish to be able to create. Generally speaking if your sequence can be expressed using functions, than all the complexity and syntactic sugar of generators can be hidden inside a decorator or a decorator-like function.



来源:https://stackoverflow.com/questions/5737196/is-there-an-expression-for-an-infinite-generator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!