Is there an expression for an infinite iterator?
Is there a straight-forward expression that can produce an infinite iterator?
This is a purely theoretical question. No need for a "practical" answer here :)
For example,开发者_JS百科 it is easy to use a generator expression to make a finite iterator:
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.
itertools
provides three infinite iterators:
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()
for x in iter(int, 1): pass
- Two-argument
iter
= zero-argument callable + sentinel value int()
always returns0
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.
you can iterate over a callable returning a constant always different than iter()'s sentinel
g1=iter(lambda:0, 1)
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
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,), {}))() }
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
.
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.
精彩评论