I have never wanted this behavior myself.  So that's 0% of the time for me.  I happily believe that Peter O'Connor wants it 90% of the time... although I guess it suggests he probably organizes his algorithms differently than I do at some broader level.  For my needs, zip() is common, and itertools.zip_longest() is somewhat uncommon, but not unheard of.

I do note that https://more-itertools.readthedocs.io also does not have this zip_equal() functionality. At least I don't see it (I could have missed it under a different name, but I looked around). This is pretty clearly the most widely used "extra stuff that might go in itertools" library.

I think part of the problem is that raising an exception when something is exhausted (other than StopIteration) is contrary to the spirit of itertools (or more_itertools).  I think part of the reason those iterator functions do not do that is that an exception often indicates "something went wrong," but if this problem occurs after an indefinitely long iteration that is later than you'd like to know.

A more common pattern, in my experience would be to put an exception in the higher-up block where an iterator is consumed.  Various "things went wrong" conditions can be checked, not exclusively that one iterator ran out before the other.

On Fri, Jul 27, 2018 at 1:03 PM Peter O'Connor <peter.ed.oconnor@gmail.com> wrote:
I find that about 90% of the time I want want to zip iterators together, I expect them to be the same length and want to throw an exception if they aren't.  Yet there is not currently a solution for this in the standard library for this, and as a result I always have to take this function everywhere I go:


    def zip_equal(*iterables):
        """
        Zip and raise exception if lengths are not equal.
    
        Taken from solution by Martijn Pieters, here:
    
        :param iterables: Iterable objects
        :return: A new iterator outputting tuples where one element comes from each iterable
        """
        sentinel = object()
        for combo in zip_longest(*iterables, fillvalue=sentinel):
            if any(sentinel is c for c in combo):
                raise ValueError('Iterables have different lengths.  Iterable(s) #{} (of 0..{}) ran out first.'.format([i for i, c in enumerate(combo) if c is sentinel], len(combo)-1))
            yield combo

Would anybody object to adding this to the standard library for Python 3.8?


_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


--
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.