有没有无限迭代器的表达式?
- 2025-04-16 08:56:00
- admin 原创
- 17
问题描述:
是否存在可以产生无限迭代器的直接表达式?
这纯粹是个理论问题,没必要给出“实际”的答案 :)
例如,使用生成器表达式来创建有限迭代器很容易:
my_gen = (0 for i in range(42))
然而,为了创建一个无限的命名空间,我需要用一个伪函数“污染”我的命名空间:
def _my_gen():
while True:
yield 0
my_gen = _my_gen()
在单独的文件中执行操作并import
稍后执行不算数。
我也知道这个方法itertools.repeat
确实有效。我很好奇有没有一个不用这个方法的单行解决方案。
解决方案 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:
for x in iter(int, 1): pass
双参数
iter
= 零参数可调用函数 + 标记值int()
总是会回来0
因此,iter(int, 1)
是一个无限迭代器。显然,这个特定主题有很多变体(尤其是在你添加lambda
其他变量之后)。一个特别值得注意的变体是iter(f, object())
,因为使用新创建的对象作为标记值几乎可以保证无限迭代器,无论第一个参数使用的可调用函数是什么。
解决方案 3:
iter()
你可以迭代一个可调用函数,返回一个与标记不同的常量
g1 = iter(lambda: 0, 1)
解决方案 4:
你的操作系统可能提供了一些可以用作无限生成器的东西。例如在 Linux 上
for i in (0 for x in open('/dev/urandom', 'rb')):
print(i)
显然,这并不像
for i in __import__('itertools').repeat(0):
print(i)
解决方案 5:
None 内部不使用定义为类/函数/生成器(而非 -表达式,而是带有 的函数yield
)的另一个无限迭代器。生成器表达式始终从另一个可迭代对象中提取,并且除了过滤和映射其项之外不执行任何操作。您无法仅使用map
和 就从有限项转换为无限项filter
,您需要while
(或者一个for
不终止的 ,这正是我们无法仅使用for
和 有限迭代器所得到的)。
琐事:PEP 3142表面上类似,但仔细检查后发现它仍然需要for
子句(因此(0 while True)
对您来说不行),即仅为 提供了快捷方式itertools.takewhile
。
解决方案 6:
相当丑陋和疯狂(但是非常有趣),但是您可以使用一些技巧从表达式构建自己的迭代器(无需按要求“污染”您的命名空间):
{ 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,), {}))() }
解决方案 7:
也许你可以使用像这样的装饰器:
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
我认为可以进一步改进,去掉那些丑陋的()
。但这取决于你希望创建的序列的复杂度。一般来说,如果你的序列可以用函数来表达,那么生成器的所有复杂性和语法糖都可以隐藏在装饰器或类似装饰器的函数中。
扫码咨询,免费领取项目管理大礼包!