Dict(x, y) -> Dict(zip(x, y))

I often find myself writing dict(zip(x, y)). Maybe that's just me or maybe not but I would like it if it were possible to spell that simply as dict(x, y). Currently dict() with two arguments is an error: $ python3 Python 3.4.3 (default, Mar 26 2015, 22:03:40) [GCC 4.9.2] on linux Type "help", "copyright", "credits" or "license" for more information.
I would prefer it if dict(x, y) would treat x as an iterable of keys and y as an iterable of corresponding values. This would be semantically equivalent to dict(zip(x, y)) except that it would raise an error if x and y don't yield the same number of items (zip truncates the longer argument). Although mostly equivalent the new construction might be more efficient, would reduce the visual noise of the redundant call to zip, and would be slightly more robust to errors. -- Oscar

this would have:
dict(((1,2),(3,4))) {1: 2, 3: 4}
dict(((1,2),(3,4)), ((5,6))) {(1, 2): 5, (3, 4): 6}
in other words, the interpretation of the first argument to dict is entirely different if there is a second argument than if there isn't one. It's quite reasonable to expect the reverse, namely that the result would be:
dict(((1,2),(3,4)), ((5,6))) {1: 2, 3: 4, 5: 6}
So adding this saves 5 characters and makes it easier to confuse readers of the code. Doesn't seem like a good idea to me. --- Bruce Check out my puzzle book and get it free here: http://J.mp/ingToConclusionsFree (available on iOS) On Sun, Feb 14, 2016 at 4:30 PM, Oscar Benjamin <oscar.j.benjamin@gmail.com> wrote:

Does it make code more readable? What about simply defining `dictzip` or `dict2` for yourself? On Feb 14, 2016 9:44 PM, "Bruce Leban" <bruce@leban.us> wrote:
entirely different if there is a second argument than if there isn't one. There is precedent for that in ``range``. (Sorry for the double mail, Bruce.)

On Feb 14, 2016, at 18:43, Bruce Leban <bruce@leban.us> wrote:
It would be nice if we could make Oscar's new parameters keyword-only: dict(keys=spam, values=eggs) Then it's _not_ the first argument that's being interpreted differently. Unfortunately, we can't do this, because it would be ambiguous with the dict(a=1, b=2) constructor. But what about a classmethod named constructor (with or without keyword-only params, depending on how long the name is): dict.kv(keys=spam, values=eggs) dict.from_keys_values(spam, eggs) That's pretty close to the idiomatic way to build dictionaries in ObjectiveC: [NSDict dictionaryWithValues:eggs forKeys:spam] ... so it's not totally unprecedented. Still, it raises the obvious question of whether "dict.kv" is much better than "dictkv", which anyone can write for himself as a one-liner if he wants it...

On 15/02/16 09:53, Andrew Barnert via Python-ideas wrote:
I would spell this dict.zip(keys, values). It brings to mind the current implementation, but allows for optimisation. It's also slightly less parenthesis heavy, which I think makes it a little more readable.
I think this is one of those cases where the gain is small enough that writing the helper function is often not worth it, but big enough that people would use it if it already existed. That might be a small window, but it's there.

On Feb 16, 2016, at 16:34, MRAB <python@mrabarnett.plus.com> wrote:
But items() is the inverse of the plain constructor, which takes an iterable of items. In other words, both items() and the constructor deal in a single iterable of zipped key-value pairs. The proposed new method or function instead deals in unzipped, separate key and value iterables. So it's the inverse of "my_dict.keys(), my_dict.values()". Of course you can also write that as "zip(*my_dict.items())", just as you can also write the new method as "dict(zip(keys, values))". At any rate, since you can write any variation of this as a one-liner, as long as you're willing to spell it "dict_spam" instead of "dict.spam", each person can call it whatever they want. :)

I’m pretty sure I would stick with ``dict(zip(keys, values))``. My code would then be backwards-compatible and wouldn’t introduce yet another thing for a newbie to need to learn about when reading my code. A new alternate constructor should follow the pattern ``dict.from_stuff`` or ``dict.fromstuff`` like ``dict.fromkeys`` or ``datetime.fromordinal``. What would you call this one? The method ``dict.setdefault`` is already awkwardly named. I suppose ``dict.get_value_and_insert_key_if_missing`` is prohibitively long. Would this new one be ``dict.from_keys_and_values``? Actually, that makes me think of one version I might be OK with: dict.fromkeys('abc', values=[0, 1, 2]) But then what would be the benefit versus ``dict(zip(keys, values))``?

this would have:
dict(((1,2),(3,4))) {1: 2, 3: 4}
dict(((1,2),(3,4)), ((5,6))) {(1, 2): 5, (3, 4): 6}
in other words, the interpretation of the first argument to dict is entirely different if there is a second argument than if there isn't one. It's quite reasonable to expect the reverse, namely that the result would be:
dict(((1,2),(3,4)), ((5,6))) {1: 2, 3: 4, 5: 6}
So adding this saves 5 characters and makes it easier to confuse readers of the code. Doesn't seem like a good idea to me. --- Bruce Check out my puzzle book and get it free here: http://J.mp/ingToConclusionsFree (available on iOS) On Sun, Feb 14, 2016 at 4:30 PM, Oscar Benjamin <oscar.j.benjamin@gmail.com> wrote:

Does it make code more readable? What about simply defining `dictzip` or `dict2` for yourself? On Feb 14, 2016 9:44 PM, "Bruce Leban" <bruce@leban.us> wrote:
entirely different if there is a second argument than if there isn't one. There is precedent for that in ``range``. (Sorry for the double mail, Bruce.)

On Feb 14, 2016, at 18:43, Bruce Leban <bruce@leban.us> wrote:
It would be nice if we could make Oscar's new parameters keyword-only: dict(keys=spam, values=eggs) Then it's _not_ the first argument that's being interpreted differently. Unfortunately, we can't do this, because it would be ambiguous with the dict(a=1, b=2) constructor. But what about a classmethod named constructor (with or without keyword-only params, depending on how long the name is): dict.kv(keys=spam, values=eggs) dict.from_keys_values(spam, eggs) That's pretty close to the idiomatic way to build dictionaries in ObjectiveC: [NSDict dictionaryWithValues:eggs forKeys:spam] ... so it's not totally unprecedented. Still, it raises the obvious question of whether "dict.kv" is much better than "dictkv", which anyone can write for himself as a one-liner if he wants it...

On 15/02/16 09:53, Andrew Barnert via Python-ideas wrote:
I would spell this dict.zip(keys, values). It brings to mind the current implementation, but allows for optimisation. It's also slightly less parenthesis heavy, which I think makes it a little more readable.
I think this is one of those cases where the gain is small enough that writing the helper function is often not worth it, but big enough that people would use it if it already existed. That might be a small window, but it's there.

On Feb 16, 2016, at 16:34, MRAB <python@mrabarnett.plus.com> wrote:
But items() is the inverse of the plain constructor, which takes an iterable of items. In other words, both items() and the constructor deal in a single iterable of zipped key-value pairs. The proposed new method or function instead deals in unzipped, separate key and value iterables. So it's the inverse of "my_dict.keys(), my_dict.values()". Of course you can also write that as "zip(*my_dict.items())", just as you can also write the new method as "dict(zip(keys, values))". At any rate, since you can write any variation of this as a one-liner, as long as you're willing to spell it "dict_spam" instead of "dict.spam", each person can call it whatever they want. :)

I’m pretty sure I would stick with ``dict(zip(keys, values))``. My code would then be backwards-compatible and wouldn’t introduce yet another thing for a newbie to need to learn about when reading my code. A new alternate constructor should follow the pattern ``dict.from_stuff`` or ``dict.fromstuff`` like ``dict.fromkeys`` or ``datetime.fromordinal``. What would you call this one? The method ``dict.setdefault`` is already awkwardly named. I suppose ``dict.get_value_and_insert_key_if_missing`` is prohibitively long. Would this new one be ``dict.from_keys_and_values``? Actually, that makes me think of one version I might be OK with: dict.fromkeys('abc', values=[0, 1, 2]) But then what would be the benefit versus ``dict(zip(keys, values))``?
participants (9)
-
Andrew Barnert
-
Bruce Leban
-
Franklin? Lee
-
Ian Foote
-
Koos Zevenhoven
-
Michael Selik
-
MRAB
-
Oscar Benjamin
-
Rob Cliffe