代码之家  ›  专栏  ›  技术社区  ›  MarkS

解包*args以在for循环中使用

  •  0
  • MarkS  · 技术社区  · 8 年前

    这是我的出发点。按原样工作。

    l1 = [1, 2, 3, 4]
    l2 = [5, 6, 7, 8]
    l3 = [9, 10, 11, 12]
    
    
    def interleave(iterable1, iterable2):
        for item1, item2 in zip(iterable1, iterable2):
            yield item1
            yield item2
    
    
    print(interleave(l1, l2))
    print('-' * 30)
    print(list(interleave(l1, l2)))
    

    如果我想扩展它以使用所有三个列表,我可以这样做:

    l1 = [1, 2, 3, 4]
    l2 = [5, 6, 7, 8]
    l3 = [9, 10, 11, 12]
    
    
    def interleave(*args):
        for item1, item2, item3 in zip(*args):
            yield item1
            yield item2
            yield item3
    
    
    print(interleave(l1, l2, l3))
    print('-' * 30)
    print(list(interleave(l1, l2, l3)))
    

    然而,我用 *args,但我的项目分配仍然是手动的。

    我想说:

    def interleave(*args):
        for *items in zip(*args):
            yield items
    

    允许我将任意数量的输入变量解包到*项中,但我得到以下错误: SyntaxError: starred assignment target must be in a list or tuple

    我不想说 *items = <something> 。我想让*项接收任意数量的输入变量。

    如果我有六个列表,我不想说第1项,第2项。。。,第6项,然后是相同数量的收益。

    这真的不是很容易扩展。

    有没有办法做我想做的事?

    2 回复  |  直到 8 年前
        1
  •  2
  •   Olivier Melançon iacob    8 年前

    对于3.3之前的Python,请使用嵌套的For循环。

    def interleave(*args):
        for items in zip(*args):
            for item in items:
                yield item
    

    对于Python 3.3+,您可以使用 yield from 对于 generator delegation 这是上面的语法糖。

    def interleave(*args):
        for items in zip(*args):
            yield from items
    

    最后,如果您需要一个更通用的解决方案来允许不同长度的列表,请使用 roundrobin 来自的函数 itertools recipes 。

    def roundrobin(*iterables):
        "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
        # Recipe credited to George Sakkis
        num_active = len(iterables)
        nexts = cycle(iter(it).__next__ for it in iterables)
        while num_active:
            try:
                for next in nexts:
                    yield next()
            except StopIteration:
                # Remove the iterator we just exhausted from the cycle.
                num_active -= 1
                nexts = cycle(islice(nexts, num_active))
    
        2
  •  0
  •   Mehdi    8 年前

    嵌套循环?

    def interleave(*args):
        for items in zip(*args): 
            for item in items:
                yield items