有无限发生器的expression式吗?
有一个直接的发生器expression式,可以产生无限的元素?
这是一个纯粹的理论问题。 这里不需要“实际”的答案:)
例如,制作一个有限的发生器很容易:
my_gen = (0 for i in xrange(42))
然而,为了创造一个无限的我需要“污染”我的命名空间与一个虚假的function:
def _my_gen(): while True: yield 0 my_gen = _my_gen()
在单独的文件中执行操作并稍后import
不计算在内。
我也知道itertools.repeat
正是这样做的。 我很好奇,如果没有一个单线的解决scheme。
for x in iter(int, 1): pass
- 双参数
iter
=零参数callable + sentinel值 -
int()
总是返回0
因此, iter(int, 1)
是一个无限的迭代器。 在这个特别的主题上显然有很多变化(尤其是一旦你把lambda
添加到混合中)。 一个特别注意的变体是iter(f, object())
,因为使用新创build的对象作为标记值几乎可以保证无限的迭代器,而不pipe用作第一个参数的可调用。
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()
你可以遍历一个可调用的函数,返回一个和iter()的标识不同的常量
g1=iter(lambda:0,1)
你的操作系统可能会提供一些可以用作无限生成器的东西。 例如在Linux上
for i in (0 for x in open('/dev/urandom')): print i
显然这不如效率
for i in __import__('itertools').repeat(0) print i
没有内部不使用定义为类/函数/生成器的其他无限迭代器(不是-expression,带有yield
的函数)。 生成器expression式总是从anoter迭代中抽取,除了筛选和映射其项目外,什么都不做。 你不能从有限的项目到无限的项目,只需要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
用法(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
我认为可以进一步改进以摆脱那些丑陋的()
。 但是,这取决于您希望能够创build的序列的复杂程度。 一般来说,如果你的序列可以用函数来表示,那么所有的复杂度和语法糖的生成器都可以隐藏在装饰器或类似装饰器的函数中。
相当丑陋和疯狂(但是非常有趣),但是你可以使用一些技巧来build立你自己的迭代器(不需要按照需要“污染”你的名字空间):
{ 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,), {}))() }
def iter_cycle(iterator): saved = [] for iterable in iterator: yield iterable saved.append(iterable) while saved: for element in saved: yield element a = iter_cycle(iter([1,2,3]))
下一个(a)→1下一个(a)→2下一个(a)→3
下一个(a) – > 1
(如一些提到的,感谢python文档https://docs.python.org/2/library/itertools.html#itertools.cycle )