是否存在可以产生无限元素的直接生成器表达式?
这是一个纯粹的理论问题。这里不需要“实际”答案:)
例如,很容易制作有限的生成器:
my_gen = (0 for i in xrange(42))
然而,要创建一个无限的,我需要用虚假函数“污染”我的命名空间:
def _my_gen():
while True:
yield 0
my_gen = _my_gen()
在单独的文件中执行操作并稍后import
- 不计算在内。
我也知道itertools.repeat
就是这样做的。我很好奇是否有一个没有它的单线解决方案。
答案 0 :(得分:165)
itertools
提供了三个无限生成器:
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,...
我不知道标准库中的任何其他内容。
因为你要求一个单行:
__import__("itertools").count()
答案 1 :(得分:109)
for x in iter(int, 1): pass
iter
=零参数可调用+哨兵值int()
始终返回0
因此,iter(int, 1)
是一个无限的迭代器。这个特定的主题显然有很多变化(特别是在你添加lambda
之后)。特别注意的一个变体是iter(f, object())
,因为使用新创建的对象作为sentinel值几乎保证无限迭代器,而不管用作第一个参数的可调用对象。
答案 2 :(得分:15)
你可以迭代一个可调用的返回一个常量不同于iter()的sentinel
g1=iter(lambda:0,1)
答案 3 :(得分:7)
您的操作系统可能会提供可用作无限生成器的内容。例如在linux上
for i in (0 for x in open('/dev/urandom')):
print i
显然这不如
那么有效for i in __import__('itertools').repeat(0)
print i
答案 4 :(得分:5)
没有在内部不使用另一个定义为类/函数/生成器的无限迭代器(不是-expression,一个带yield
的函数)。生成器表达式始终从anoter iterable中抽取,除了过滤和映射其项之外什么也不做。你不能只使用map
和filter
从有限项转到无限项,你需要while
(或者for
不会终止,这正是我们不能只使用for
和有限迭代器。)
琐事:PEP 3142表面上相似,但经过仔细检查后,它似乎仍然需要for
子句(所以对你来说没有(0 while True)
),即只提供{的快捷方式{1}}。
答案 5 :(得分:3)
相当丑陋和疯狂(非常有趣),但你可以通过使用一些技巧(没有"污染"你的命名空间根据需要)从表达式构建自己的迭代器:
{ 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,), {}))() }
答案 6 :(得分:2)
也许您可以使用像这样的装饰器:
def generator(first):
def wrap(func):
def seq():
x = first
while True:
yield x
x = func(x)
return seq
return wrap
用法(1):
@generator(0)
def blah(x):
return x + 1
for i in blah():
print i
用法(2)
for i in generator(0)(lambda x: x + 1)():
print i
我认为可以进一步改进以摆脱那些丑陋的()
。但是,它取决于您希望能够创建的序列的复杂性。一般来说,如果您的序列可以使用函数表达,那么生成器的所有复杂性和语法糖都可以隐藏在装饰器或类似装饰器的函数中。