[Python-ideas] Unpacking a dict
Ethan Furman
ethan at stoneleaf.us
Wed May 25 19:41:57 EDT 2016
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.
> 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.
--
~Ethan~
More information about the Python-ideas
mailing list