1

I have a dictionary as such:

test = {'tuple':(1, 2, 3, 4), 'string':'foo', 'integer':5}

In order to keep down wasted space, I'd like to unpack these values into individual variables. I know that it is possible to unpack the keys of a dictionary:

>>> a, b, c = test
>>> print(a, b, c)
tuple string integer

But what I'd like to do is unpack the dictionary values. Somehthing like this:

>>> tuple, string, integer = test
>>> print(tuple, string, integer)
(1, 2, 3, 4) string 5

Is this possible? If not, I think if the variables you unpack to correspond to values inside the dictionary, it should unpack the values into the appropriate variable (like is shown above).

Or is my only way to do this is like this?:

>>> tuple, string, integer = test['tuple'], test['string'], test['integer']
James Wright
  • 1,293
  • 2
  • 16
  • 32
  • If anyone's thinking of suggesting `locals().update`, no, that doesn't work. – user2357112 Apr 25 '17 at 17:57
  • 2
    Also, keep in mind that pre-Python 3.6, dicts are unordered, and even in Python 3.6, ordering is officially an implementation detail, and the dict might not have been constructed in the order you expect. – user2357112 Apr 25 '17 at 18:00
  • 3
    http://stackoverflow.com/questions/2597278/python-load-variables-in-a-dict-into-namespace possible duplicate – Serge Apr 25 '17 at 18:02
  • 3
    Just keep the dictionary. – mkrieger1 Apr 25 '17 at 18:10
  • I second what @mkrieger1, why not just *use the dictionary*? – juanpa.arrivillaga Apr 25 '17 at 18:13
  • I'm still vaguely surprised that despite all the weird unpacking generalizations Python has introduced, there's still no way to unpack a mapping in an assignment, like `a, b, c = **{'a': 1, 'b': 2, 'c': 3}` or something. – user2357112 Apr 25 '17 at 18:13
  • Exactly why I'm asking @user2357112. I've just recently discovered all the random unpacking rules (which are quite helpful) and figured that maybe there was something that would do it that I couldn't find. – James Wright Apr 25 '17 at 19:11

4 Answers4

1

Assuming you are using a version of python earlier than 3.6 just sort the values by the keys, then unpack in alphabetical order...

integer, string, tup = [i[1] for i in sorted(test.items(), key=lambda x: x[0])]

Then even if you add more keys, you just have to remember the alphabetical order, although I can't see how practical this approach would be over just using the dict

Verbal_Kint
  • 1,366
  • 3
  • 19
  • 35
  • Beats options that assume a dict order, but you have to remember to use alphabetical order everywhere and remember things like whether `'A'` comes before or after `'b'` and whether `'a1'` comes before or after `'ab'`. – user2357112 Apr 25 '17 at 18:18
  • @user2357112 check last sentence in my answer – Verbal_Kint Apr 25 '17 at 18:20
1

What I've settled on doing is simply:

tuple, string, integer = [test[x] for x in ('tuple', 'string', 'integer')] 

It cleans things up enough for me and get's close to what I'm after.

Still think that tuple, string, integer = **test (as suggested by @user2357112) should be a thing. Makes a lot of sense to me.

Edit: Future me now realizes that doing tuple, string, integer = **test isn't possible since dictionaries aren't ordered. Therefore in that syntax there's no way to tell python which dictionary entries it should unpack into which variables. That said, I dealing with an ordered dict, then it could work.

James Wright
  • 1,293
  • 2
  • 16
  • 32
0

Supposing that the number of keys on the dict is static you can retrieve it first with values() and then assign to vars:

>>> tuple, string, integer = test.values()
>>> print(tuple, string, integer)
(1, 2, 3, 4) foo 5

More information in https://docs.python.org/3.6/library/stdtypes.html#dict

Edit: As said in comments, python doesn't guarantee order in keys so, a better solution is:

>>> for key in test:
       globals()[key] = test[key]
>>> print(tuple, string, integer)
(1, 2, 3, 4) foo 5

Also, this solve the problem with variable dict lengths.

VMRuiz
  • 1,931
  • 12
  • 20
0

If order is not an issue you could use the following:

test = {'tuple':(1, 2, 3, 4), 'string':'foo', 'integer':5}

print([test[x] for x in test.keys()])

Note that this outputs a list, if you want it to be in the format you showed before you could use:

test = {'tuple':(1, 2, 3, 4), 'string':'foo', 'integer':5}

print(' '.join([str(test[x]) for x in test.keys()]))

And of course, if order is important you could make a sorted list from test.keys() and iterate over it, e.g. by using sorted(test.keys()).

Good luck!

Edit:

inty, stringy, tuply = [test[x] for x in sorted(test.keys())]

Would yield the desired result in this case, but note that adding more keys might change the order!

Fox31415
  • 41
  • 4