On 2017-11-29 14:21, Greg Ewing wrote:
C Anthony Risinger wrote:

`a, b, ...` to me says "pull out a and b and throw away the rest"...
  > The mere presence of more
characters (...) implies something else will *happen* to the remaining
items, not that they will be skipped.

It seems that many people think about unpacking rather
differently from the way I do. I think the difference
is procedural vs. declarative.

To my way of thinking, something like

     a, b, c = x

is a pattern-matching operation. It's declaring that
x is a sequence of three things, and giving names to
those things. It's not saying to *do* anything to x.

With that interpretation,

     a, b, ... = x

is declaring that x is a sequence of at least two
items, and giving names to the first two. The ellipsis
just means that there could be more items, but we
don't want to give them names.

On the other hand, some people seem to be interpreting
the word "unpack" as in "unpack a suitcase", i.e. the
suitcase is empty afterwards. But unpacking has never
meant that in Python! If it did, then

     x = [1, 2, 3]
     a, b, c = x

would leave x == [] afterwards.

The only case where unpacking behaves like that is when
the rhs is an iterator rather than a sequence, in which
case a side effect is unavoidable. The question then is
what the side effect should be.

That's an interesting analysis, but I don't think your view is really the right one. It *is* unpacking a suitcase, it's just that *if necessary* the suitcase is constructed just in time for you to unpack it. In other words, the suitcase is not the list [1, 2, 3], but an iterator over this list. This is the same as the behavior for "for" loops: if you do "for item in [1, 2, 3]", the actual thing you're unrolling is an iterator over the list. In some sense the point of the iterable/iterator distinction is to distinguish suitcases (iterators) from things-that-produce-suitcases-on-demand (iterables). It's just that Python syntax (very nicely) allows us to omit the explicit iter() call. The fact that iteration is taking place is specified by the context; that could be a for loop, or it could be multiple assignment targets, but it's iteration all the same.

I would argue that, since the side effect is something
that's not really wanted, it should be as *small* as
possible. By that argument,

     a, b, ... = some_iterator

should do as *little* as possible to fulfill what's
being asked, i.e. give names to the first two items
produced by the rhs. Consuming those two items is
unavoidable, but there's no need to consume any more.

I see your point, but I think that middle ground doesn't really give the benefits of either. If you expect your suitcase to remain unopened, it's pretty cold comfort to find that someone has opened it and taken only your pants and shoes but left the rest. If the side effect isn't wanted, you really need the RHS to be something that isn't affected (i.e., a re-iterable). It does seem that in some cases you may want the iterator to be exhausted, and in others not, but I don't think it's a good idea to try to "hide" the unpacking by limiting the number of iterations. The important difference is between any irreversible unpacking at all, and none at all.


--
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is no path, and leave a trail."
   --author unknown
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to