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

Reply via email to