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
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/WAPV6KEAW6PREDBMS47OVSTYNQWEON3K/
Code of Conduct: http://python.org/psf/codeofconduct/