问题:无限生成器有表达式吗?
是否有一个可以生成无限元素的简单生成器表达式?
这是一个纯粹的理论问题。此处无需“实用”答案:)
例如,很容易制作一个有限生成器:
my_gen = (0 for i in xrange(42))
但是,要制作一个无限个,我需要用虚假函数“污染”我的命名空间:
def _my_gen():
while True:
yield 0
my_gen = _my_gen()
在单独的文件中处理,import
以后-ing不计算在内。
我也知道这itertools.repeat
完全可以做到。我很好奇是否有没有这种情况的一线解决方案。
回答 0
for x in iter(int, 1): pass
- 两参数
iter
=零参数可调用+哨兵值 int()
总是回来0
因此,iter(int, 1)
是一个无限的迭代器。显然,此特定主题有很多变体(尤其是一旦添加lambda
到组合中)。特别注意的一个变体是iter(f, object())
,因为使用新创建的对象作为哨兵值几乎可以保证无限迭代器,而与用作第一个参数的可调用对象无关。
回答 1
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()
回答 2
您可以遍历可调用的可返回的常量,该常量始终与iter()的哨兵不同
g1=iter(lambda:0, 1)
回答 3
您的操作系统可能提供可用作无限生成器的功能。例如在Linux上
for i in (0 for x in open('/dev/urandom')):
print i
显然,这没有效率
for i in __import__('itertools').repeat(0)
print i
回答 4
没有一个在内部不使用另一个定义为类/函数/生成器的无限迭代器(不是-expression,带有的函数yield
)。生成器表达式始终从可迭代的迭代器中提取,除了过滤和映射其项外什么也不做。您不能只从有限的项目到无限的项目map
和或者filter
您需要while
(或者一个for
不会终止的项,这正是我们仅使用for
有限迭代器所不能拥有的)。
琐事:PEP 3142在表面上是相似的,但是仔细检查似乎仍然需要该for
子句(因此(0 while True)
对您而言没有),即仅提供的快捷方式itertools.takewhile
。
回答 5
相当丑陋和疯狂(但是非常有趣),但是您可以通过使用一些技巧从表达式构建自己的迭代器(无需根据需要“污染”您的命名空间):
{ 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
例如,也许您可以使用这样的装饰器:
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
我认为可以进一步改善摆脱这些丑陋的状况()
。但是,这取决于您希望创建的序列的复杂性。一般来说,如果可以使用函数来表达序列,那么生成器的所有复杂性和语法糖都可以隐藏在装饰器或类似装饰器的函数内部。