Python 是否有一些内置的标记序列的最后一个?

Python 是否有一些内置的标记序列的最后一个?,python,generator,Python,Generator,我需要这样的东西: >>> for i in mark_last([1, 2, 3]): ... print(i) ... (1, False) (2, False) (3, True) 我是这样实现的,但是 def mark_last(li): items = iter(items) try: prev = next(items) except StopIteration: return for item

我需要这样的东西:

>>> for i in mark_last([1, 2, 3]):
...  print(i)
... 
(1, False)
(2, False)
(3, True)
我是这样实现的,但是

def mark_last(li):
    items = iter(items)
    try:
        prev = next(items)
    except StopIteration:
        return
    for item in items:
        yield prev, False
        prev = item
    yield prev, True

有内置的吗?还是用一种较短的方法?可能是与
itertools.groupby()相结合的东西
?-不接受使用
len()
的技巧,因为它们不适用于生成器。

您可以根据
iwindow
定义
mark\u last
,它返回一个滑动参数 一个小房间的窗户

import itertools as IT

def iwindow(iterable, n=2):
    """
    Returns a sliding window (of width n) over data from the sequence.
    s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...
    """
    iterables = IT.tee(iterable, n)
    iterables = (IT.islice(it, pos, None) for pos, it in enumerate(iterables))
    for result in IT.izip(*iterables):
        yield result

def mark_last(iterable):
    for i, j in iwindow(iterable):
        yield i, False
    yield j, True

for i in mark_last([1, 2, 3]):
    print(i)
屈服

(1, False)
(2, False)
(3, True)
请注意,通过在Python3中传递对
mark_last

的需要,您可能可以直接解决
iwindow
的问题+

对于大型列表,这可能对性能有点困难

>>> def mark_last(iterable):
...     *others, last = iterable
...     for element in others:
...             yield (element, False)
...     yield (last, True)
...
>>> for i in mark_last([1, 2, 3]):
...     print(i)
...
(1, False)
(2, False)
(3, True)
:

如果目标列表包含一个前缀为星号的目标, 称为“星号”目标:该对象必须是至少具有 目标列表中目标的数量减去一最新版本 序列的第一项从左到右分配给 目标在星号目标之前。序列的最后一项是 分配给星号目标之后的目标。名单 然后将序列中的剩余项目分配给星号目标 (列表可以为空)

这是在
*others,last=iterable
行上执行的操作,但相反

是否有一些内置的标记序列的最后一个

不,没有

您的功能很好,除了两点:

  • 它如何处理空序列
  • 你不应该
    raisestopIteration
    ,而应该
    break
    ;最终,
    raisestopIteration
    将导致
    运行时错误
    ()

  • 一个更简洁的版本就是你所给予的

    def mark_last(items):
        items = iter(items)
    
        prev = next(items)
        for item in items:
            yield prev, False
            prev = item
    
        yield item, True
    

    请注意,使用裸
    next
    来引发
    StopIteration
    是不可取的,但是,您可能希望使用显式
    try…除了

    确实不会使代码变短,但也许这不应该是目标
    iwindow
    是一种更常用的设计模式。如果将
    iwindow
    保存在工具箱中(例如,在
    util.py
    模块中),就可以解决许多滑动窗口问题
    mark_last
    只是一个例子。你的2号就是一个很好的例子。关于1号:空序列→ 无元素→ 没有最后的元素→ 无需标记因此,根据设计,打印循环根本不被输入。@RobertSiemer:如果你看一下
    mark_last
    last=next(li)
    ——这与第2行的问题相同:它现在可以工作了,但在后PEP479时代不会。是否存在无限迭代器的最后一个元素?如果您知道有可能在无限迭代器上调用此函数,您应该使用Veedrac的解决方案。是的,
    for…in
    更好。我将编辑我的问题。