[Python-ideas] Yet More Unpacking Generalizations (or, Dictionary Literals as lvalues)
Steven D'Aprano
steve at pearwood.info
Wed Aug 12 18:38:16 CEST 2015
On Wed, Aug 12, 2015 at 09:57:03AM -0400, Scott Sanderson wrote:
> Hi All,
>
> Occasionally I find myself wanting to unpack the values of a dictionary
> into local variables of a function. This most often occurs when
> marshalling values to/from some serialization format.
I think that anything that is only needed "occasionally" doesn't have a
strong claim to deserve syntax.
> For example:
>
> def do_stuff_from_json(json_dict):
> actual_dict = json.loads(json_dict)
> foo = actual_dict['foo']
> bar = actual_dict['bar']
> # Do stuff with foo and bar.
Seems reasonable and not too much of a burden to me. If I needed a lot
of keys, I'd do:
# sequence unpacking version
spam, eggs, cheese, foo, bar, baz = [actual_dict[key] for
key in "spam eggs cheese foo bar baz".split()]
> In the same spirit as allowing argument unpacking into tuples or lists,
> what I'd really like to be able write is something like:
>
> def do_stuff_from_json(json_dict):
> # Assigns variables in the **values** of the lefthand side by doing lookups
> # of the corresponding keys in the result of the righthand side expression.
> {'foo': foo, 'bar': bar} = json.loads(json_dict)
I think the sequence unpacking version above reads much better than
this hypothetical dict unpacking version:
{'foo': foo, 'bar': bar, 'baz': baz, 'spam': spam,
'eggs': eggs, 'cheese': cheese} = json.loads(json_dict)
Both are roughly as verbose, both have a little duplication, but the
sequence unpacking version requires far fewer quotation marks and other
punctuation. I also think it's much more readable, and of course the big
advantage of it is that it works right now, you don't have to wait two
or three years to start using it in production.
If there is a downside to the sequence unpacking version, it is that it
requires a temporary variable actual_dict, but that's not a real
problem.
I don't think dict unpacking is needed when you have only two or three
variables, and I don't think your suggested syntax is readable when you
have many variables. So I would be -1 on this suggestion.
However, if you wanted to think outside the box, it's a pity that
locals() is not writable. If it were, we could do:
locals().update(json.loads(json_dict))
although of course that might update too many local names. So, just
throwing it out there for discussion:
- Make locals() writable. If the compiler detects that locals() may be
written to, that will have to disable the fast local variable access
for that specific function.
More practical, and in the spirit of tuple unpacking:
spam, eggs, cheese = **expression
being equivalent to:
_tmp = expression
spam = _tmp['spam']
eggs = _tmp['eggs']
cheese = _tmp['cheese']
del _tmp
except that _tmp is never actually created/deleted.
This is easier to write and simpler to read, and doesn't allow nested
unpacking. (I consider that last point to be a positive feature, not a
lack.)
--
Steve
More information about the Python-ideas
mailing list