Python 变量作为 dict 的键

在 Python (2.7)中有更简单的方法吗?注意: 这不是什么花哨的东西,就像把所有的局部变量放入一个字典。只有我在列表中指定的那些。

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)
263315 次浏览

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

A one-liner is:-

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

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])

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.

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

a = "something"
randround = {}
randround['A'] = "%s" % a

Worked.

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.

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}

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.