Home > other >  How does iterating over 3 elements at the same time using a combination of zip, * and *3 work?
How does iterating over 3 elements at the same time using a combination of zip, * and *3 work?

Time:02-28

I'm trying to iterate over 3 elements at a time using the following (which seems to work):

for a, b, c in zip(*[iter(accounts_iter)]*3):
    print(a)
    print(b)
    print(c)
  1. accounts_iter is a list of tuples I created.
  2. iter(accounts_iter) unpacks accounts_iter into a list iterator, so its still a list of tuples just that its now iterable

Here's where I struggle to understand.

  • *[iter(accounts_iter)] unpacks the list in Step 2 into separate tuples, so no longer a list of tuples but individual tuples
  • *[iter(accounts_iter)]*3 multiplies that by 3

In my output, I do not seem to have duplicates, but am indeed able to process 3 items each loop.

But won't I have 3 copies of the same tuple once zip(*[iter(accounts_iter)]*3) happens?

CodePudding user response:

Unwinding layers of "cleverness", you may find this equivalent spelling easier to follow:

x = iter(accounts_iter)
for a, b, c in zip(*[x, x, x]):
    print(a, b, c)

which is, in turn, equivalent to the even less-clever:

x = iter(accounts_iter)
for a, b, c in zip(x, x, x):
    print(a, b, c)

Now it should start to become clear. There is only a single iterator object, x. On each iteration, zip(), under the covers, calls next(x) 3 times, once for each iterator object passed to it. But it's the same iterator object here each time. So it delivers the first 3 next(x) results, and leaves the shared iterator object waiting to deliver its 4th result next. Lather, rinse, repeat.

BTW, I suspect you're parsing *[iter(accounts_iter)]*3 incorrectly in your head. The trailing *3 happens first, and then the prefix * is applied to the 3-element list *3 created. f(*iterable) is a shortcut for calling f() with a variable number of arguments, one for each object iterable delivers.

  • Related