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)
accounts_iter
is a list of tuples I created.iter(accounts_iter)
unpacksaccounts_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 inStep 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.