[Python-ideas] + operator on generators

David Mertz mertz at gnosis.cx
Tue Jun 27 03:47:40 EDT 2017


On Tue, Jun 27, 2017 at 12:12 AM, Steven D'Aprano <steve at pearwood.info>
wrote:

> > > I have a counter-proposal: introduce the iterator chaining operator
> "&":
> > >     iterable & iterable --> itertools.chain(iterable, iterable)
> >
> > In [1]: import numpy as np
> > In [2]: import itertools
> > In [3]: a, b = np.array([1,2,3]), np.array([4,5,6])
> > In [4]: a & b
> > Out[4]: array([0, 0, 2])
> > In [5]: a + b
> > Out[5]: array([5, 7, 9])
> > In [6]: list(itertools.chain(a, b))
> > Out[6]: [1, 2, 3, 4, 5, 6]
> >
> > These are all distinct, useful, and well-defined behaviors.
>
> - keep the existing __and__ and __rand__ behaviour;
> - if they are not defined, and both operands x, y are iterable,
>   return chain(x, y);
>

I understand.  But it invites confusion about just what the `&` operator
will do for a given iterable.  For NumPy itself, you don't really want to
spell `chain(a, b)` so much.  But you CAN, they are iterables.  The
idiomatic way is:

    >>> np.concat((a,b))
    array([1, 2, 3, 4, 5, 6])

However, for "any old iterable" it feels very strange to need to inspect
the .__and__() and .__rand__ ()  methods of the things on both sides before
you know WHAT operator it is.

Maybe if you are confident a and b are exactly NumPy arrays it is obvious,
but what about:

    from some_array_library import a
    from other_array_library import b

What do you think `a & b` will do under your proposal? Yes, I understand
it's deterministic... but it's far from *obvious*.  This isn't even doing
something pathological like defining both `.__iter__()` and `.__and__()` on
the same class... which honestly, isn't even all that pathological; I can
imagine real-world use cases.

I think that chaining iterators is common enough and important enough in
> Python 3 to deserve an operator. While lists are still important, a lot
> of things which were lists are now lazily generated iterators, and we
> often need to concatenate them. itertools.chain() is less convenient
> than it should be.
>

I actually completely agree! I just wish I could think of a good character
that doesn't have some very different meaning in other well-known contexts
(even among iterables).

Some straw men:

    both = a ⊕ b
    both = a ⇢ b

Either of those look pretty nice to me, but neither is easy to enter on
most keyboards.

I think I wouldn't mind `&` if it only worked on iteraTORS.  But then it
loses many of the use cases.  I'd like this, after all:

    for i in range(10)⇢[20,19,18]⇢itertools.count(100):
        if i>N: break
        ...


-- 
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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20170627/46a0ee37/attachment-0001.html>


More information about the Python-ideas mailing list