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