Pythonification of the asterisk-based collection packing/unpacking syntax

Steven D'Aprano steve+comp.lang.python at pearwood.info
Tue Dec 27 18:10:42 EST 2011


On Sun, 25 Dec 2011 07:47:20 -0800, Eelco wrote:

> Explicit and implicit are not well-defined terms, 

We can at least agree on that.

> but I would say that
> at the moment the signal is implicit, in the sense that one cannot see
> what is going on by considering the rhs in isolation. 

That is a ridiculous argument. If you ignore half the statement, of 
course you can't tell what is going on.


> Normally in
> python, an assignment just binds the rhs to the identifiers on the lhs,
> but in case of collection (un)packing, this rule that holds almost all
> of the time is broken, and the assignment statement implies a far more
> complicated construct, with a far more subtle meaning, and non-constant
> time complexity.

Python assignment in general is not constant time.

If the left hand side is a single identifier (a name, a dotted attribute, 
a subscription or slice, etc.) then the assignment is arguably constant 
time (hand-waving away complications like attribute access, hash table 
collisions, descriptors, etc.); but if the left hand side is a list of 
targets, e.g.:

a, b, c = sequence

then the assignment is O(N). Python has to walk the sequence (actually, 
any iterator) and assign each of N items to N identifiers, hence O(N) not 
O(1).

The trivial case of a single value on the left hand side:

x = 1

is just the degenerate case for N=1.


> Thats not a terrible thing, but a little extra explicitness there would
> not hurt, 

I think it will. It makes the assignment more verbose to no benefit.


> and like I argued many times before, it is a nice unification
> with the situation where the unpacking can not be implicit, like inside
> a function call rather than assignment.

That's one opinion; but there's no need for any "extra explicitness" 
since the definition of assignment in Python already explicitly includes 
iterable unpacking. How much explicitness do you need?



>>     n = len(::sequence)
> 
> Now you are just discrediting yourself in terms of having any idea what
> you are talking about.

::sequence is redundant and unnecessary whether it is inside a function 
call to len or on the right hand side of an assignment. In both cases, it 
adds nothing to the code except noise.

Your proposal is surreal. You started off this conversation arguing that 
the existing idiom for extended iterator unpacking, e.g.

head, *tail = sequence

is too hard to understand because it uses punctuation, and have ended up 
recommending that we replace it with:

head, tail:: = ::sequence 

instead (in the generic case where you don't want to use a different type 
for tail).

Your original use-case, where you want to change the type of tail from a 
list to something else, is simply solved by one extra line of code:

head, *tail = sequence
tail = tuple(tail)


You have written thousands of words to save one line in an idiom which 
you claim is very uncommon. Perhaps your understanding of "pythonic" is 
not as good as you imagine.



-- 
Steven



More information about the Python-list mailing list