Syntactic sugar for assignment statements: one value to multiple targets?
Terry Reedy
tjreedy at udel.edu
Wed Aug 17 12:12:47 EDT 2011
The issue behind this thread is that for immutable objects, binding to n
copies has the same effect as n bindings to one object (so one does not
really have to know which one is doing), whereas the two are different
for mutable objects (so one does have to know). In short, identity
matters for mutables but not for immutables. Python programmers must
learn both this and the fact that Python does not make copies unless asked.
Adding a special case exception to the latter to mask the former does
not seem like a good idea.
On 8/17/2011 5:26 AM, gc wrote:
> It has only one very modest function, which is to unpack
>
> a, b, c, d, e = *dict()
*expression has already been proposed to generally mean what it does in
function calls -- unpack the iterator in place.
funnylist = [1,2,*dict,99,100]
# == [1,2]+list(dict)+[99,100]
would interpolate the keys of the dict into the list.
There is a tracker issue for this -- it would be a follow-on to the
addition of *traget in assignments.
In a real sense, "a,b = iterable" *already* means "a,b = *iterable". If
*iterable had been in general use from the beginning, presume the latter
is how we would write sequence unpacking for assignments.
> a, b, c, d, e = dict(), dict(), dict(), dict(), dict()
*expression will not be changed in meaning to magically re-evaluate an
expression some multiple number of times according to code elsewhere.
> so that you have n separate objects instead of one. If you want the
> same object duplicated five times, you'd best use a=b=c=d=e=dict().
Not 'duplicated', but 'bound'.
> (I'd guess that 90% of the people who try the a=b=c version actually
> *want* separate objects and are surprised at what they get--I made
> that mistake a few times!
Guessing that 90% of people are like you is likely to be wrong.
I think this use case (for more than 2 or 3 copies) is pretty rare for
most people.
Where many people do trip up is "array = [[0]*i]*j", expecting to get j
copies of [0]*i rather than j bindings of one object. But then, they
must have the same wrong idea that [0]*i makes i copies of 0. For
immutable 0, the misunderstanding does not matter. For mutable [0]*i, it
does. People *must* learn that sequence multiplication multiplies
bindings, not (copies of) objects. Both multiple copy problems have the
same solution:
array = [[0]*i for _ in range(j)]
a,b,c,d,e = [dict() for _ in range(5)]
The fact that the number of assignment sources (possibly after implicit
unpacking) and targets have to match, unless one uses *target, and that
both sides need to be changed if one is, is true of all assignments, not
just this rare case.
>--but changing either behavior would be a
> very bad idea. This proposed syntax would be the Right Way to get
> separate objects.)
It would be very Wrong as it already has a very different meaning.
--
Terry Jan Reedy
More information about the Python-list
mailing list