1

I'd like to unpack dicts like:

one, two, three, four = unpack(this_dict)

where

this_dict = {'one': 1, 'two': 2, 'three': 3, 'four': 4}

my only issue is unpack needs to know what names it was gonna be assigned to. How do you do this in python? Thank you

codyc4321
  • 9,014
  • 22
  • 92
  • 165
  • 4
    you don't. Why would you need to do this – Adam Smith Apr 18 '16 at 20:02
  • 5
    Use the keys to assign, dicts are unordered so unpacking and expecting an order does not make sense – Padraic Cunningham Apr 18 '16 at 20:05
  • 2
    Somewhat related: http://stackoverflow.com/questions/4010840/generating-variable-names-on-fly-in-python. Though the common approach is contrary to your desired result - use a dictionary. – alecxe Apr 18 '16 at 20:06
  • 2
    You can't. When the function `unpack` is called, it has no knowledge of the left hand side of the assignment statement. – Jared Goguen Apr 18 '16 at 20:06
  • 2
    You simply cannot, a dict is a based on a hash table built on top of an list in RAM, where the data is stored based on the binary hash of the key, using this hash last 3 bits, but when a slot matching these last 3 bits is already taken, the algorithm falls back to a secondary backup, which if taken forces the algorithm to again fall back to a third backup hash, and so on.... Hence the keys not being store and therefore returned in their insertion order. – DevLounge Apr 18 '16 at 20:11
  • 1
    Unpacking a `dict` into a `tuple` defeats the purpose of the former being an unordered map. If you are going to use a `dict` operate on it like a `dict`. The way you intend to do it needs more information about the order, which you have to supply involving some form of indexing. So it's just redundant and pointless. You are better off using a `list` of `tuple`s or better yet, a `namedtuple` – C Panda Apr 18 '16 at 22:42

2 Answers2

6

Dicts are unordered so if you wanted to unpack in a certain order you would need to use the keys, you could make a function to do it passing in whatever keys you want to access:

from operator import itemgetter
def unpack(d, *args):
    return itemgetter(*args)(d)
one, two, three, four = unpack(this_dict, "one" ,"two" ,"three" ,"four")

print(one, two, three, four)

Or using map:

def unpack(d, *args):
    return map(d.get, args) 
one, two, three, four = unpack(this_dict, "one" ,"two" ,"three" ,"four")

print(one, two, three, four)

The difference between the two is the first would give you a KeyError if you passed a key that did not exist, the latter would set the variable to None for any missing key so that is something to keep in mind.

Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
3

You definitely shouldn't be doing this. However, if you are in the module-level scope, you can add your dictionary to globals().

this_dict = {'one': 1, 'two': 2, 'three': 3, 'four': 4}
globals().update(this_dict)

print one, two, three, four
# 1 2 3 4

Note that this approach is dangerous if your dictionary contains keys like list, int, False, and so on. You could technically do this inside a function or class, but that would be even more worse.

Jared Goguen
  • 8,772
  • 2
  • 18
  • 36
  • It should be noted that this is dangerous, for example if the `dict` contains an entry with the key `int`. – RoadieRich Apr 18 '16 at 20:35
  • I edited your answer slightly, so as not to imply the later approach was safer. – RoadieRich Apr 18 '16 at 20:48
  • Actually neither of these will really work in practice, because [modifying the result of `locals()` doesn't generally work](https://docs.python.org/2/library/functions.html#locals). You can only do that with `globals()`. These scripts worked because the code is at the top level where `globals() is locals()`. If you wrap them in a function they fail. – Alex Hall Apr 18 '16 at 21:25
  • @AlexHall o.o I explicitly tested that before answering and it was working fine. I must have over-looked something. I'll update the answer accordingly. – Jared Goguen Apr 18 '16 at 21:44