[Python-ideas] Unpacking a dict
Michael Selik
michael.selik at gmail.com
Wed May 25 18:52:01 EDT 2016
I'm responding here to Sven, Random832, and Ethan.
On Wed, May 25, 2016 at 10:08 AM Sven R. Kunze <srkunze at mail.de> wrote:
> I for one find this one of the shortest proposals compared to other recent
> proposals I have seen. :)
>
If it's easy to explain, it might be a good idea :-)
On Wed, May 25, 2016 at 10:40 AM Random832 <random832 at fastmail.com> wrote:
> On Wed, May 25, 2016, at 09:11, Michael Selik wrote:
> > Clojure also supports mapping destructuring. Let's add that to Python!
> >
> > py> mapping = {"a": 1, "b": 2, "c": 3}
> > py> {"a": x, "b": y, "c": z} = mapping
>
> How is this better than:
> py> mapping = {"a": 1, "b": 2, "c": 3}
> py> x, y, z = mapping[k] for k in ("a", "b", "c")
>
I think the thread has formed a consensus that there are at least 2 clear
use cases for unpacking. Not surprisingly, they're the same use cases for
both tuple unpacking and dict unpacking.
1. declarative schema validation while simultaneously binding variables
2. declaratively extracting a subset of the elements
In your example, what if the dict has more keys than you are looping over?
Look at the other part of my proposal:
py> mapping = {"a": 1, "b": 2, "c": 3}
py> {"a": x, "b": y} = mapping
Traceback:
ValueError: too many keys to unpack
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.
On Wed, May 25, 2016 at 4:14 PM Ethan Furman <ethan at stoneleaf.us> 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 = **mapping`` I
would expect ``a, b = *iterable``.
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
Unpacking a dict should mirror a dict display.
py> {'x': a, 'y': b} = {'x': 1, 'y': 2}
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.
On Wed, May 25, 2016 at 11:18 AM Paul Moore <p.f.moore at gmail.com> 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}
If you need to ignore many, we need to extend dict unpacking the same way
that tuple unpacking was extended in PEP 3132.
py> (a, b, *rest) = (1, 2, 3, 4)
py> a, b, rest
(1, 2, (3, 4))
py> {'x': a, 'y', b, **rest} = {'x': 1, 'y': 2, 'z': 3, 'w': 4}
py> a, b, rest
(1, 2, {'w': 4, 'z': 3})
Sure, **rest isn't valid in a dict display, but it's the same with tuple
unpacking: *rest isn't valid in a tuple display.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20160525/8965bbbe/attachment.html>
More information about the Python-ideas
mailing list