Python variables as keys to dict

Question:

Is there an easier way to do this in Python (2.7)?: Note: This isn’t anything fancy, like putting all local variables into a dictionary. Just the ones I specify in a list.

apple = 1
banana = 'f'
carrot = 3
fruitdict = {}

# I want to set the key equal to variable name, and value equal to variable value
# is there a more Pythonic way to get {'apple': 1, 'banana': 'f', 'carrot': 3}?

for x in [apple, banana, carrot]:
    fruitdict[x] = x # (Won't work)
Asked By: atp

||

Answers:

The globals() function returns a dictionary containing all your global variables.

>>> apple = 1
>>> banana = 'f'
>>> carrot = 3
>>> globals()
{'carrot': 3, 'apple': 1, '__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'banana': 'f'}

There is also a similar function called locals().

I realise this is probably not exactly what you want, but it may provide some insight into how Python provides access to your variables.

Edit: It sounds like your problem may be better solved by simply using a dictionary in the first place:

fruitdict = {}
fruitdict['apple'] = 1
fruitdict['banana'] = 'f'
fruitdict['carrot'] = 3
Answered By: Greg Hewgill

A one-liner is:-

fruitdict = dict(zip(('apple','banana','carrot'), (1,'f', '3'))
Answered By: Dantalion
for i in ('apple', 'banana', 'carrot'):
    fruitdict[i] = locals()[i]
Answered By: dr jimbob

why you don’t do the opposite :

fruitdict = { 
      'apple':1,
      'banana':'f',
      'carrot':3,
}

locals().update(fruitdict)

Update :

don’t use the code above check the comment.

by the way why you don’t mark the vars that you want to get i don’t know
maybe like this:

# All the vars that i want to get are followed by _fruit
apple_fruit = 1
carrot_fruit = 'f'

for var in locals():
    if var.endswith('fruit'):
       you_dict.update({var:locals()[var])
Answered By: mouad

Well this is a bit, umm … non-Pythonic … ugly … hackish …

Here’s a snippet of code assuming you want to create a dictionary of all the local variables you
create after a specific checkpoint is taken:

checkpoint = [ 'checkpoint' ] + locals().keys()[:]
## Various local assigments here ...
var_keys_since_checkpoint = set(locals().keys()) - set(checkpoint)
new_vars = dict()
for each in var_keys_since_checkpoint:
   new_vars[each] = locals()[each]

Note that we explicitly add the ‘checkpoint’ key into our capture of the locals().keys() I’m also explicitly taking a slice of that though it shouldn’t be necessary in this case since the reference has to be flattened to add it to the [ ‘checkpoint’ ] list. However, if you were using a variant of this code and tried to shortcut out the ['checkpoint'] + portion (because that key was already inlocals(), for example) ... then, without the [:] slice you could end up with a reference to thelocals().keys()` whose values would change as you added variables.

Offhand I can’t think of a way to call something like new_vars.update() with a list of keys to be added/updated. So thefor loop is most portable. I suppose a dictionary comprehension could be used in more recent versions of Python. However that woudl seem to be nothing more than a round of code golf.

Answered By: Jim Dennis

This question has practically been answered, but I just wanted to say it was funny that you said

This isn’t anything fancy, like
putting all local variables into a
dictionary.

Because it is actually “fancier”

what you want is:

apple = 1
banana = 'f'
carrot = 3
fruitdict = {}

# I want to set the key equal to variable name, and value equal to variable value
# is there a more Pythonic way to get {'apple': 1, 'banana': 'f', 'carrot': 3}?

names= 'apple banana carrot'.split() # I'm just being lazy for this post
items = globals()                    # or locals()

for name in names:
    fruitdict[name] = items[name]

Honestly, what you are doing is just copying items from one dictionary to another.

(Greg Hewgill practically gave the whole answer, I just made it complete)

…and like people suggested, you should probably be putting these in the dictionary in the first place, but I’ll assume that for some reason you can’t

Answered By: Terence Honles
a = "something"
randround = {}
randround['A'] = "%s" % a

Worked.

Answered By: user1734291

Based on the answer by mouad, here’s a more pythonic way to select the variables based on a prefix:

# All the vars that I want to get start with fruit_
fruit_apple = 1
fruit_carrot = 'f'
rotten = 666

prefix = 'fruit_'
sourcedict = locals()
fruitdict = { v[len(prefix):] : sourcedict[v]
              for v in sourcedict
              if v.startswith(prefix) }
# fruitdict = {'carrot': 'f', 'apple': 1}

You can even put that in a function with prefix and sourcedict as arguments.

Answered By: Arnout

Here it is in one line, without having to retype any of the variables or their values:

fruitdict.update({k:v for k,v in locals().copy().iteritems() if k[:2] != '__' and k != 'fruitdict'})

Try:

to_dict = lambda **k: k
apple = 1
banana = 'f'
carrot = 3
to_dict(apple=apple, banana=banana, carrot=carrot)
#{'apple': 1, 'banana': 'f', 'carrot': 3}
Answered By: Prv

Not the most elegant solution, and only works 90% of the time:

def vardict(*args):
    ns = inspect.stack()[1][0].f_locals
    retval = {}
    for a in args:
        found = False
        for k, v in ns.items():
            if a is v:
                retval[k] = v
                if found:
                    raise ValueError("Value found in more than one local variable: " + str(a))
                found = True
        if found:
            continue
        if 'self' in ns:
            for k, v in ns['self'].__dict__.items():
                if a is v:
                    retval[k] = v
                    if found:
                        raise ValueError("Value found in more than one instance attribute: " + str(a))
                    found = True
        if found:
            continue
        for k, v in globals().items():
            if a is v:
                retval[k] = v
                if found:
                    raise ValueError("Value found in more than one global variable: " + str(a))
                found = True
        assert found, "Couldn't find one of the parameters."
    return retval

You’ll run into problems if you store the same reference in multiple variables, but also if multiple variables store the same small int, since these get interned.

Answered By: Aleksandr Dubinsky
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.