假设我有一个生成器,我想从中提取第 10 个元素但忽略前 9 个元素。生成器是我编写的一个函数,看起来像这样:
def myGenerator(arg1, arg2):
for i in arg1:
myState = doSomeWork(i, arg2)
yield expensiveOperation(myState)
现在我可以使用它并像这样从中获取第 10 个索引:
myGen = myGenerator(list1, list2)
tenthElement = next(itertools.islice(myGen,10,11))
我想知道这是否会运行 expensiveOperation
十次,还是只运行一次?
(编辑:它调用了 10 次,但下一部分是我感兴趣的部分。)
是否有任何方法可以优化掉其他 9 个对 expensiveOperation
的调用,因为它们已被丢弃? (为清楚起见进行了编辑)
我可以想到其他几个不涉及使用生成器函数的解决方案,它们会给出我想要的,但语法不如通过替换 return 将迭代函数转换为生成器那么干净
和 yield
。
编辑:
我不一定要尝试解决这个特定问题,而是要寻找一种廉价地“滚动”生成器的方法。在我目前正在处理的真实案例中,当我第一次调用 myGenerator
时,我实际上并不知道我想要哪个索引。我可能会抓取第 15 个索引,然后是第 27 个,然后是第 82 个。我可能想出一种在第一次调用时切到第 15 个的方法,但下次我需要再滚动 12 个。
最佳答案
生成器与它的消费者是隔离的——它不知道什么被扔掉了。所以,是的,它在每一步都进行了昂贵的操作。
我只想将昂贵的操作移到生成器之外:
def myGenerator(arg1, arg2):
for i in arg1:
myState = doSomeWork(i, arg2)
yield myState
myGen = myGenerator(list1, list2)
tenthElement = expensiveOperation(next(itertools.islice(myGen,10,11)))
关于Python 生成器索引优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7904816/