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