[Python-ideas] Unpacking a dict

MRAB python at mrabarnett.plus.com
Wed May 25 19:58:55 EDT 2016


On 2016-05-26 00:41, Ethan Furman wrote:
> On 05/25/2016 03:52 PM, Michael Selik wrote:
>
>> I really like Sven's example.
>>
>> py> mapping = {"a": 1, "b": 2, "c": 3}
>>      py>{"a": x, "b": y, "c": 2} = mapping
>>      Traceback:
>>      ValueError: key 'c' does not match value 2
>>
>> Even if we don't implement this feature in the first version of dict
>> unpacking, we should keep the option open.
>
> Ugh, no.  That is not dict unpacking, it's dict matching and unpacking,
> which is way beyond the simplicity of just unpacking.
>
>> On Wed, May 25, 2016 at 4:14 PM Ethan Furman wrote:
>>>
>>> The proposal is this:
>>>     a, b = **mapping
>>>
>>> The advantages:
>>> - much more readable
>>> - less duplication
>>
>>
>> Why doesn't that work for tuple unpacking?
>>      py> a, b = *iterable
>>      SyntaxError
>>
>> Whatever the reasons, that syntax wasn't chosen for tuple unpacking.
>> Dict unpacking should mimic tuple unpacking. If I saw ``a, b =
>
> Good point.  So it should just be:
>
>    a, b = mapping
>
> or
>    a, b, **_ = mapping  # when you don't care about the rest
>
>
>> Unpacking a tuple mirrors a tuple display.
>>
>>      py> (a, b) = (1, 2)
>>      py> (a, b) = (1, 2, 3)
>>      ValueError: too many values to unpack, expected 2
>
> I think that most Pythonistas would say:
>
>    a, b = 1, 2  # look ma!  no round brackets!
>
>> Unpacking a dict should mirror a dict display.
>>
>>      py> {'x': a, 'y': b} = {'x': 1, 'y': 2}
>
> Absolutely not, at least not for the simple case.  A simple tuple/list
> unpack looks like
>
>    a, b, c = an_iterable
>
> while a more complicated one looks like
>
>    a, b, c = an_iterable[7], an_iterable[3], an_iterable[10]
>
> So a simple dict unpack should look like
>
>    some_dict = dict(a=99, b=44, c=37)
>    a, b, c = some_dict
>
> and if we don't need all the items
>
>    a, b, **_ = some_dict
>
> and if we want to rename the keys on extraction
>
>    x, y, z = some_dict['a'], some_dict['b'], some_dict['c']
>
> or, as Random pointed out
>
>    x, y, z = [some_dict[k] for k in ('a', 'b', 'c')]
>
> which has a nice symmetry to it.
>
Could we use 'as', which is already used for renaming in imports?

     a as x, b as y, c as z = some_dict

or, perhaps:

     'a' as x, 'b' as y, 'c' as z = some_dict

which would cater for keys that aren't valid as identifiers.

>
>> py> {'x': a, 'y': b} = {'x': 1, 'y': 2, 'z': 3}
>>      ValueError: too many keys to unpack, expected {'x', 'y'}
>>
>> As Brendan and others have mentioned, the more concise syntax you're
>> proposing will not support non-string keys and cannot be enhanced to
>> support Erlang/Clojure/etc-style matching on values.
>
> And as I have mentioned, matching syntax is out-of-scope for an
> unpacking proposal.  At most, it should be a "let's not paint ourselves
> into a corner" type of concern -- and I must admit I don't see why
>
>    a, b, c = some_dict
>
> rules out
>
>   {'x': a, 'y':b} = some_dict
>
> as a pattern-matching construct.
>
>
>> On Wed, May 25, 2016 at 11:18 AM Paul Moore wrote:
>>>
>>> get a set of elements and *ignore* the rest:
>>
>> If it's just one or two, that's easy. Use an underscore to indicate you
>> don't care. Again, I'm trying to mirror a dict display. This is the same
>> way that tuple unpacking solves the problem.
>>
>>      py> (a, b, _) = (1, 2, 3)
>>      py> {'x': a, 'y': b, 'z': _} = {'x': 1, 'y': 2, 'z': 3}
>
> Since you've repeated yourself, I will too.  ;)
>
> The parenthesis are legal, but usually unnecessary noise, when
> creating/unpacking a tuple.
>



More information about the Python-ideas mailing list