简体   繁体   English

从生成器中打印项目

[英]Printing items out of a generator

I am practicing printing out items yielded by a generator function. 我正在练习打印生成器函数产生的项目。

This works perfectly fine: 这工作得很好:

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b


sumfib = 0
for i in fibonacci():
    if i >= 4000000:
        break
    elif i % 2 == 0:
        sumfib += i

print(sumfib)

But the following code is yielding: 但是下面的代码产生了:

list1 = ['f', 'o', 'o', 'b', 'a', 'r']
list2 = ['hello', 'world']
list3 = ['1', '2', '3', '4']


def ziplike(*args):
    x = zip(*args)
    yield x


for item in ziplike(list1, list2, list3):
    print(item)

What I want to print is each item from each list sequentially, exhausted when the shortest list is exhausted. 我要打印的是按顺序从每个列表中提取的每个项目,当最短列表用尽时,它就会用尽。 I have it working without a generator, but I am trying to wrap my hands around generators. 我在没有发电机的情况下也能正常工作,但是我试图将手缠在发电机上。

I want to print this: 我要打印此:

f
hello
1
o
world
2

The first element in each, followed by the second, etc., until the shortest list is exhausted. 每个元素中的第一个元素,然后是第二个元素,依此类推,直到用尽了最短的列表。 I want to be able to feed in any number of iterables, hence my use of *args . 我希望能够提供任意数量的可迭代对象,因此我使用*args

NOTE My working, non-generator variant uses itertools: 注意我的非发电机工作版本使用itertools:

newlist = list(zip(list1, list2, list3))

temp = list(itertools.chain(*newlist))

I was trying to avoid that, if possible. 如果可能的话,我试图避免这种情况。

You can make your non-generator version work lazily too, just avoid the list() calls and use itertools.chain.from_iterable() : 您也可以让您的非生成器版本也懒洋洋地工作,只需避免调用list()并使用itertools.chain.from_iterable()

newlist = zip(list1, list2, list3)
temp = itertools.chain.from_iterable(newlist)

As for your implementation; 至于你的实现; you yielded the whole zip() result, not individual elements from that. 您产生了整个zip()结果,而不是其中的单个元素。 Delegate to the zip() iterator with yield from : 使用yield from委托给zip()迭代器:

def ziplike(*args):
    x = zip(*args)
    yield from x

This still produces the row tuples from the zip() call; 这仍然会从zip()调用中生成行元组; you'd need to loop over each contained tuple too: 您还需要遍历每个包含的元组:

def ziplike(*args):
    x = zip(*args)
    for tup in x:
        yield from tup

to chain the tuple contents. 链接元组内容。

Demo of the latter: 后者的演示:

>>> list1 = ['f', 'o', 'o', 'b', 'a', 'r']
>>> list2 = ['hello', 'world']
>>> list3 = ['1', '2', '3', '4']
>>> def ziplike(*args):
...     x = zip(*args)
...     for tup in x:
...         yield from tup
...
>>> for item in ziplike(list1, list2, list3):
...     print(item)
...
f
hello
1
o
world
2

Yielding x yields the entire iterable. 产生x产生整个可迭代。 You need to yield from x . 您需要 x屈服。

yield from x

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM