[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