views:

107

answers:

8

Hello,

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)

Edit: the number assignments were meaningless...changing them.

+2  A: 

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
Greg Hewgill
Sorry, I must have edited after you were writing your answer. I only need the variables I specify, not all locals() or globals()
Jasie
@Jasie: I added an example of simply using a dictionary in the first place, instead of messing around with variables.
Greg Hewgill
+1  A: 

locals() and globals()?

Paulo Scardine
A: 

If you want to bind the locations of the variables themselves, there's this:

>>> apple = 1
>>> banana = 'f'
>>> carrot = 3
>>> fruitdict = {}
>>> fruitdict['apple'] = lambda : apple
>>> fruitdict['banana'] = lambda : banana
>>> fruitdict['carrot'] = lambda : carrot
>>> for k in fruitdict.keys():
...     print k, fruitdict[k]()
... 
carrot 3
apple 1
banana f
>>> apple = 7
>>> for k in fruitdict.keys():
...     print k, fruitdict[k]()
... 
carrot 3
apple 7
banana f
cjrh
Thanks, but the numbers were random assignments (didn't need a range()).
Jasie
+1  A: 

A one-liner is:-

fruitdict = dict(zip(('apple','banana','carrot'), (1,'f', '3'))
Dantalion
Thanks, but the numbers were random assignments (didn't need a range()).
Jasie
Now there's two lists
Dantalion
+1  A: 
for i in ('apple', 'banana', 'carrot'):
    fruitdict[i] = locals()[i]
jimbob
This is the way to go. Thanks.
Jasie
A: 

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])
singularity
Updating `locals()` like that is truly evil.
Greg Hewgill
As a friend of mine says: 'dark voodoo'
cjrh
agree, but my understanding of his question is that he want to get only variable that are __fruit and legume__ ; which is basically impossible unless he could teach his program to make difference between __fruit and legume__ and other stuff , or maybe i just complicate thing maybe he just want "carrot , banana , apple" vars :)
singularity
updating locals() is **forbidden** http://docs.python.org/library/functions.html#locals
gnibbler
A: 

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.

Jim Dennis
A: 

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

Terence Honles
so I guess I didn't see jimbob's post... practically the same thing, just doesn't call locals/globals more than once
Terence Honles
I'm don't think calling globals more than once would actually be more efficient.
jimbob
E.g., if you do items = locals(); id(locals()) == id(items) you would get equality. Or if you did items=locals(); b = 3 ; items['b'] it will find the new variable b, since it didn't actually copy the locals dict to items (which would be slower). If you had done items=locals().copy() there may have been a minor difference; but then again the copying step is probably slower than accessing the small number of items from the locals dict.
jimbob