在Python中从无限生成器获取子集列表

在Python中从无限生成器获取子集列表,python,generator,enumerate,Python,Generator,Enumerate,摘要:我正在努力学习itertools.islice 我试图找到一种最好的方法来获得一个列表,该列表由一个无限生成函数返回的子集组成。例如,我可能需要生成器中第1000到2000项的列表 这是我的示例生成器: def infinite_counter(): i = 0 while True: i += 2 yield i 这些值是我希望列表启动和停止的生成器的返回索引: start = 1000 end = 2000 方法1:列表理解(失败)

摘要:我正在努力学习itertools.islice


我试图找到一种最好的方法来获得一个列表,该列表由一个无限生成函数返回的子集组成。例如,我可能需要生成器中第1000到2000项的列表

这是我的示例生成器:

def infinite_counter():
    i = 0
    while True:
        i += 2
        yield i
这些值是我希望列表启动和停止的生成器的返回索引:

start = 1000
end = 2000
方法1:列表理解(失败)

这是可行的,但感觉真的像一个黑客。这也很难理解,但是我错误地认为它会比方法3快

方法3:简易方法(有效)

这是我第一次想到这样做,在我责怪自己不是蟒蛇之前。我感到惊讶的是,这在时间安排上几乎与方法2完全相同

方法4:itertools.takewhile(有效)

正如预期的那样,这比方法2和3慢得多

总的来说,我很惊讶地看到方法3的时间安排与方法2的时间安排非常接近。这是更多的代码,但更容易让人遵循。这就是我目前实现的方式

是否有其他的方法值得我考虑或更好的解决? 编辑:

方法6itertools.islice(获胜者)

这比具有列表理解功能的初始itertools.islice解决方案略快:

[val for val in itertools.islice(infinite_counter(), start_ind, end_ind)]

令人惊讶的是找到正确的方法

对于那些记分的人,我的计时发现如下:

方法6=单位时间

方法2~=2.5*单位时间

from itertools import islice

list(islice(infinite_counter(), 1000, 2000))
方法3~=3*单位时间

from itertools import islice

list(islice(infinite_counter(), 1000, 2000))
方法4~=4.2*单位时间

from itertools import islice

list(islice(infinite_counter(), 1000, 2000))
方法5~=4*单位时间

from itertools import islice

list(islice(infinite_counter(), 1000, 2000))

请注意

list(next(iter([])) if ind > end else val for ind,val in enumerate(infinite_counter()) if ind >= start)
转换到这个

def _secret():
    for ind, val in enumerate(infinite_counter()):
        if ind >= start:
            if ind > end:
                yield list(next(iter([])))

            else:
                yield val

list(_secret())
这是很容易改进的

def _secret():
    for ind, val in enumerate(infinite_counter()):
        if ind < start:
            continue

        if ind > end:
            break

        yield val

list(_secret())
def_secret():
对于ind,枚举中的val(无穷多计数器()):
如果ind<开始:
持续
如果ind>结束:
打破
屈服值
列表(_secret())

这对我来说很好。

找到正确的方法能做什么,真令人惊讶。谢谢无论你如何解决那些看起来很糟糕的事情,总能找到正确的解决方案。
from itertools import islice

list(islice(infinite_counter(), 1000, 2000))
list(next(iter([])) if ind > end else val for ind,val in enumerate(infinite_counter()) if ind >= start)
def _secret():
    for ind, val in enumerate(infinite_counter()):
        if ind >= start:
            if ind > end:
                yield list(next(iter([])))

            else:
                yield val

list(_secret())
def _secret():
    for ind, val in enumerate(infinite_counter()):
        if ind < start:
            continue

        if ind > end:
            break

        yield val

list(_secret())