On Mon, Apr 20, 2020 at 07:47:51PM -0700, Andrew Barnert wrote:
counter = itertools.count() yield from zip(counter, itertools.chain(headers, [''], body, ['']) lines = next(counter)
That gives you one more than the number of lines yielded.
Yeah, I screwed that up in simplifying the real code without testing the result. And your version gives one _less_ than the number yielded.
No, my version repeats the last number yielded, which is precisely what you wanted (as I understand it). See below. py> def test(): ... headers = body = '' ... for t in enumerate(itertools.chain(headers, [''], body, [''])): ... yield t ... print(t[0]) ... py> list(test()) 1 [(0, ''), (1, '')]
(With either enumerate(xs) or zip(counter, xs) the last element will be (len(xs)-1, xs[-1]).
Um, yes? That's because both enumerate and counter start from zero by default. I would have asked you why you were counting your lines starting from zero instead of using `enumerate(xs, 1)` but I thought that was intentional.
Your version has the additional problem that if the iterable is empty, t is not off by one but unbound (or bound to some stale old value)—but that’s not possible in my example, and probably not in most similar examples.
But the iterable is never empty, because you always yield at least two blanks.
Anyway, that’s exactly why I want to make sure the fencepost behavior is actually defined for this new proposal. Any reasonable answer is probably fine; people probably won’t run into wanting the leftovers, but if they ever do, as long as the docs say what should be there, they’ll work it out.
Like you worked out the behaviour of counter and zip? *wink* I think you were overthinking it. The simplest, foolproof way to get the number of items yielded is to count them with enumerate starting with 1: count = 0 for count, item in enumerate(something, 1): yield item print(count) I don't believe this zip_strict proposal would help you in this situation. I think it will make it worse, because it will encourage people to use this anti-pattern: seq = list(something) for count, item in zip_strict(range(1, len(seq)+1), seq): yield item print(count) "just to be sure". -- Steven