Python变量作为dict的键


77

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

1
可以在字典中定义变量吗?就像fruitdict = dict(apple = 1,banana = 2,胡萝卜= 3)吗?
jimbob博士2010年

并非如此,每个变量都有很多代码,因此不可读。
atp

我假设您知道自己的代码没有按照注释的说明进行操作?除非在locals()之类的名称空间字典中找到所需的内容,否则不能从对象返回名称,但是可以编写一个函数在名称空间字典中查找这些变量,并将找到的值分配给该键。请参阅jimbob的答案。
托马斯

是的,抱歉,我应该澄清一下。
atp

Answers:


79
for i in ('apple', 'banana', 'carrot'):
    fruitdict[i] = locals()[i]

16
一线dict([(i, locals()[i]) for i in ('apple', 'banana', 'carrot')])
迪尼亚

3
尽管这个问题大约是2.7,但请注意,上述单行代码在Python 3中不起作用,因为它locals()显然指向列表理解的范围。
罗普,

那么,Python 3的解决方案是什么?
Dr_Zaszuś

loc=locals()之前设置过的@Dr_Zaszuś dict([(i, loc[i]) for in ('apple', 'banana', 'carrot')])
贝尔

19

globals()函数返回一个包含所有全局变量的字典。

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

还有一个类似的函数称为locals()

我意识到这可能不完全是您想要的,但是它可以提供一些关于Python如何提供对变量访问的见解。

编辑:听起来您的问题也许可以通过首先使用字典来更好地解决:

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

抱歉,您写完答案后,我必须进行了编辑。我只需要指定的变量,而不是所有的locals()或globals()
atp 2010年

@Jasie:我添加了一个示例,该示例首先只是使用字典,而不是搞乱变量。
格雷格·希吉尔

6

一线是:-

fruitdict = dict(zip(('apple','banana','carrot'), (1,'f', '3'))

谢谢,但是数字是随机分配的(不需要range())。
atp

3

这里是一行,而无需重新输入任何变量或其值:

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

2

根据mouad的回答,这是一种基于前缀选择变量的更Python方式:

# 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}

您甚至可以将其放在带有前缀和sourcedict作为参数的函数中。


1

好吧,这有点,嗯...非Pythonic ...丑陋... hackish ...

这是一段代码,假定您要在采用特定检查点之后创建一个包含所有本地变量的字典:

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]

请注意,我们已将'checkpoint'键显式添加到我们的捕获中locals().keys() ,尽管在这种情况下,由于不必将引用展平以将其添加到['checkpoint中, ']列表。但是,如果您使用的是此代码的变体,并尝试使['checkpoint'] + portion (because that key was already inlocals(), for example) ... then, without the [:] slice you could end up with a reference to thelocals()。keys()`变短,则其值会随着添加变量而改变。

副手,我想不出一种方法来调用类似new_vars.update()要添加/更新的键的列表。因此,for循环是最可移植的。我想可以在最新版本的Python中使用字典理解。但是,woudl似乎不过是一场打高尔夫球而已。


-1

这个问题实际上已经回答了,但是我只是想说你说的很有趣

这并不是什么幻想,就像将所有局部变量放入字典一样。

因为它实际上是“鸽友”

您想要的是:

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]

老实说,您正在做的只是将项目从一本字典复制到另一本。

(格雷格·休吉尔(Greg Hewgill)实际上给出了整个答案,我只是说完整了)

...而且就像人们建议的那样,您可能应该首先将它们放在字典中,但是我认为由于某种原因您不能


所以我想我没有看过jimbob的帖子...几乎是同一回事,只是不止一次打电话给本地人/全球人
Terence Honles 2010年

我不认为多次致电全球人士实际上会更有效率。
jimbob博士2010年

例如,如果您执行item = locals(); id(locals())== id(items)您将获得平等。或者如果您执行了items = locals(); b = 3; items ['b']会找到新变量b,因为它实际上并未将locals dict复制到item(这会比较慢)。如果您完成了items = locals()。copy(),则可能会有细微的差别。但是话又说回来,复制步骤可能比从本地字典中访问少量项目慢。
jimbob博士

-1

尝试:

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}

1
与简单地做有dict(apple=apple, banana=banana, carrot=carrot)什么不同?
巴斯特·阿里

-1

这不是最优雅的解决方案,仅在90%的时间内有效:

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

如果将相同的引用存储在多个变量中,但是如果多个变量存储的是相同的int小数,则会遇到问题,因为这些变量会被插入。


-2

为什么你不做相反的事情:

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

locals().update(fruitdict)

更新:

不要使用上面的代码检查注释。

顺便说一下,为什么不标记要获取的变量,我不知道也许是这样的:

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

4
那样的更新locals()确实是邪恶的。
格雷格·休吉尔 Greg Hewgill)2010年

作为我的一个朋友说:“黑巫术”
教徒 Caleb Hattingh,2010年

同意,但是我对他的问题的理解是他只想得到水果和豆类的变量。这基本上是不可能的,除非他可以教他的程序来区分水果和豆类以及其他东西,或者我只是使事情复杂化,也许他只想要“胡萝卜,香蕉,苹果” vars :)
mouad 2010年


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

工作了。


1
应该是{'a' : 'something'},您正在得到{'A' : 'something'}...您正在对密钥进行硬编码A
DarkCygnus
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.