我可以在Python中将迭代器的内容“拼接”到我自己的迭代器中吗?

时间:2011-02-23 17:57:22

标签: python iterator

假设我有一个迭代器,我想在它之前或之后添加一些元素。我能想到的唯一方法是使用显式循环:

def myiter(other_iter):
    yield "First element"
    for item in other_iter:
        yield item
    yield "Last element"

有更好或更有效的方法吗?是否有一个名称如yield_items_from的函数可以像这样使用?

def myiter(other_iter):
    yield "First element"
    yield_items_from(other_iter)
    yield "Last element"

编辑:

好的,我过度简化了我的例子。这是一个更好的:

假设我有一个迭代器other_iter,它返回一个非负整数的递增序列。我想返回一个从零开始计数的迭代器,对于other_iter返回的数字返回1,否则返回0。例如,如果other_iter产生[1,4,5,7],我想得到[0,1,0,0,1,1,0,1]。有一种有效且可读的方法吗?

5 个答案:

答案 0 :(得分:3)

不,没有像yield_items_from这样的内容,尽管有一个草案提案要在PEP 380中添加一个Python 3.X。

对于当前的Python,显式循环是从子迭代器中产生的唯一方法。但是,它的效率相当高,而且这是一种惯用的方式,所以你不应该为冗长而烦恼。

如果您需要做的只是在迭代器的前面或后面添加新项,那么您只需使用itertools.chain来创建一个新的迭代器。您可以使用它将多个迭代器链接在一起,或者通过将它们包装在列表中来追加/添加单个项目。

new_iter = itertools.chain(['prefix item'], old_iter, appended_iter)

答案 1 :(得分:2)

使用itertools.chain

import itertools

for item in itertools.chain(["First element"],other_iter,["Last element"]):
    ...

关于编辑过的问题,如何:

import itertools as it

def bincounter(iterable):
    counter=it.count()
    for elt in iterable:
        for c in counter:
            if c < elt:
                yield 0
            else:
                yield 1
                break

other_iter=iter([1,4,5,7])    
print(list(bincounter(other_iter)))
# [0, 1, 0, 0, 1, 1, 0, 1]

答案 2 :(得分:0)

Itertools有效,但如果你想要一个替代品:

def ch(*iters):    
    for it in iters:
        for elem in it:
            yield elem    

s1=["First element"] 
s2=['middle 1', 'middle 2', 'middle 3']
s3=["last element"]

for i in ch(s1,s2,s3):
    print i

从您的编辑

更新

您的具体要求可以通过以下方式满足:

def in_l(l):
    count = 0
    while count<=max(l):
        if count in l: 
            count += 1
            yield 1
        else: 
            count += 1
            yield 0   

print list(in_l([1,4,5,7]))

请注意l必须是序列,而不是生成器对象。序列有长度和最大值。生成器可能是无限的,因此没有长度,下标,可计算的最大值。

我认为这个难题还有更多内容?您所描述的内容听起来有许多其他设计模式可以更好地实现它。你看过一个简单的状态机吗?

答案 3 :(得分:0)

回答你的新问题:

other_iter = [1,4,5,7]

def flags( items ):
    c = 0
    for this in items:
        while c < this:
            yield 0
            c += 1
        yield 1

print list(flags(other_iter))

我很确定没有内置或帮助器可以做到这一点。

答案 4 :(得分:0)

从Python 3.3开始,您可以使用yield from语法形式。

def myiter(other_iter):
    yield "First element"
    yield from other_iter
    yield "Last element"

有关详情,请参见PEP 380 -- Syntax for Delegating to a Subgenerator,有关简要的教程,请参见What's New in Python 3.3帖子。