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