假设我有一个迭代器,我想在它之前或之后添加一些元素。我能想到的唯一方法是使用显式循环:
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]。有一种有效且可读的方法吗?
答案 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)
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帖子。