如何编写生成器以返回可迭代对象中的所有但最后一个项?

5 投票
5 回答
2183 浏览
提问于 2025-04-15 20:18

我昨天问了一些类似的问题[1, 2],得到了很好的回答,但我现在的技术水平还不够,没法自己写出这么复杂的生成器。

我想知道怎么写一个生成器,让它在最后一个项目时抛出StopIteration,而不是返回这个项目。

我在想,或许我应该一次询问两个值,看看第二个值是不是StopIteration。如果是的话,那我就不返回第一个值,而是抛出这个StopIteration。不过,如果第二个值不是StopIteration,我又得记住这个值。

我不知道怎么自己写出来。请帮帮我。

举个例子,如果可迭代对象是[1, 2, 3],那么这个生成器应该返回1和2。

谢谢,Boda Cydo。

[1] 如何修改Python中的生成器?

[2] 如何判断Python生成器中的值是“倒数第二”?

5 个回答

2

more_itertools这个项目有一个工具,可以模拟itertools.islice,而且它支持负数索引:

import more_itertools as mit

list(mit.islice_extended([1, 2, 3], None, -1))
# [1, 2]
2

首先,真的需要用到生成器吗?听起来用Python的切片语法就能完美解决这个问题:

result = my_range[ : -1]

也就是说:从第一个项目开始,到倒数第二个项目结束。

13

这个代码应该能解决问题:

def allbutlast(iterable):
    it = iter(iterable)
    current = it.next()
    for i in it:
        yield current
        current = i


>>> list(allbutlast([1,2,3]))
[1, 2]

这个代码会遍历整个列表,并返回前一个项目,所以最后一个项目不会被返回。
需要注意的是,如果你在空列表([])和只有一个元素的列表([1])上运行这个代码,结果都会是一个空列表。

撰写回答