Emulating Python zip() Function I'm brushing up on Python, working my way through Python Workout. One of the exercises is to emulate the Python zip() function, assuming each iterable passed to the function is of the same length. Here's what I've come up with:
def myzip(*args):
    result = [[] for _ in range(len(args[0]))]
    for i, v in enumerate(args):
        for j, w in enumerate(v):
            result[j].append(w)

    for i, v in enumerate(result):
        result[i] = tuple(v)

    return result

While my function works, I have a hunch there must be a more succinct way of achieving the same thing (forgoing the nested loops). Is there? I'm running Python 3.9.
You should not apply len, because that requires that the first argument be at least as strong as a Collection, when zip should not need that guarantee and should only need Iterable which is a weaker type.
Gathering results in memory can be inefficient and lead to memory starvation. It's worth noting that an in-memory approach might actually execute more quickly than a generator but you would want to test this.
Attempt some type hinting. The amount of type-hinting you can do here is fairly limited, but you can do better than nothing.
It's also worth noting that the official documentation has a reference implementation.
Suggested
from typing import Any, Iterable, Tuple


def myzip(*args: Iterable[Any]) -&gt; Iterable[Tuple[Any, ...]]:
    first_iter, *other_iters = (iter(a) for a in args)

    for first in first_iter:
        yield (first, *(
            next(other) for other in other_iters
        ))


for a, b in myzip([1, 2, 3], [4, 5, 6]):
    print(a, b)

Alternate
This version does not need to wrap the first argument in an iterator.
def myzip(first_iter: Iterable[Any], *args: Iterable[Any]) -&gt; Iterable[Tuple[Any, ...]]:
    others = [iter(a) for a in args]

    for first in first_iter:
        yield (first, *(
            next(other) for other in others
        ))