将字典划分为变量

时间:2012-06-22 13:04:46

标签: python python-2.7

我正在学习Python,目前正在学习更多的字典学习。

我在想;

如果我有一个字典,如:d = {'key_1': 'value_a', 'key_2': 'value_b'},我希望单独/将此字典划分为变量,其中每个变量都是字典中的一个键,每个变量值都是字典中该键的值。

实现这一目标的最好的pythonic方式是什么?

d = {'key_1': 'value_a', 'key_2': 'value_b'}
#perform the command and get
key_1 = 'value_a'
key_2 = 'value_b'

我尝试过:key_1, key_2 = d但它没有用。

基本上我正在寻求专家的智慧,以找出是否有更好的方法将2行代码减少为一行。

注意:这不是动态变量创建。

10 个答案:

答案 0 :(得分:15)

之前未提及的解决方案是

dictget = lambda d, *k: [d[i] for i in k]

然后使用它:

key_1, key_2 = dictget(d, 'key_1', 'key_2')

它的优点是即使要检索更多变量,它也是可读的。

然而,更具可读性的是“真实”功能,例如

def dictget(d, *k):
    """Get the values corresponding to the given keys in the provided dict."""
    return [d[i] for i in k]
    # or maybe
    return (d[i] for i in k) # if we suppose that we have bigger sets of result
    # or, equivalent to this
    for i in k:
        yield d[i]

它也支持使用docstring进行评论,并且是首选。

答案 1 :(得分:13)

问题是dicts是无序的,所以你不能使用d.values()的简单解包。您当然可以先按键对dict进行排序,然后解压缩值:

# Note: in python 3, items() functions as iteritems() did
#       in older versions of Python; use it instead
ds = sorted(d.iteritems())
name0, name1, name2..., namen = [v[1] for v in ds]

至少在一个对象中,您也可以执行以下操作:

for k, v in dict.iteritems():
    setattr(self, k, v)

此外,正如我在上面的评论中所提到的,如果您可以将所有需要解压缩字典的逻辑作为函数中的变量,您可以这样做:

def func(**kwargs):
    # Do stuff with labeled args

func(**d)

答案 2 :(得分:13)

现有的答案可行,但它们基本上都是重新实现Python标准库中已存在的函数:operator.itemgetter()

来自docs

  

返回一个可调用对象,该对象使用操作数的__getitem __()方法从其操作数中获取项。如果指定了多个项,则返回一个查找值元组。例如:

     

在f = itemgetter(2)之后,调用f(r)返回r [2]。

     

在g = itemgetter(2,5,3)之后,调用g(r)返回(r [2],r [5],r [3])。

换句话说,你的结构化字典赋值就像:

from operator import itemgetter

d = {'key_1': 'value_a', 'key_2': 'value_b'}
key_1, key_2 = itemgetter('key_1', 'key_2')(d)

# prints "Key 1: value_a, Key 2: value_b"
print("Key 1: {}, Key 2: {}".format(key_1, key_2))

答案 3 :(得分:2)

我实际上有一个用例,我将__init__方法的所有参数都引入到对象构造的self命名空间中:

vars(self).update(somedict)

vars函数可以获得与传递的对象关联的“命名空间”的字典。但是,由于CPython实现细节,这不适用于函数中的locals。因此,它不应该适用于所有口译员。

对于全局命名空间,您可以将vars(self)替换为globals(),但这确实表明您的逻辑存在问题。如上所述,对于局部变量,这无论如何都不会起作用(即使你为dict赋值了它也会NameError。)

答案 4 :(得分:2)

如果你很勇敢,你可以这样做:

for k, v in d.items():
    locals()[k] = v

但勇敢可能还不够 - 你可能也必须鲁莽等等。

如果你想成为像@ecatmur这样鲁莽的英雄,你可以这样做:

locals().update(d)

但是现在OP已经更新了他的问题并回答了评论,看来,这不是他真正想做的事情。仅供记录:动态创建变量有充分的理由 - 即使这里的每个人都认为它不是pythonic。通过动态更改范围,可以很好地解决许多解释器样式问题。只是以受控的方式做到这一点。并且......呃,不要将它部署到某个生产站点;)

答案 5 :(得分:1)

我认为这应该可以解决你的问题

d = {'key_1': 'value_a', 'key_2': 'value_b'}
for k,v in d.items():
    exec '%s=%s'%(k,v)

答案 6 :(得分:1)

var1, var2 = (lambda key1, key2: (key1, key2))(**d)

如果您想让任何阅读代码的人头疼,您可以使用匿名函数来解压缩这样的值。

答案 7 :(得分:0)

不建议动态声明变量,因为找到变量名的来源变得非常困难。也就是说,可以将解决方案Dynamic variable name in python合并在一起,但我不推荐它。使用普通的旧词典可能会更好。

答案 8 :(得分:0)

这是一个在调用堆栈帧上使用Python的inspect模块确定如何从提供的字典中提取正确值的解决方案。现在,唯一的检查是确保每个输出变量都有一个可用的值,但是如果需要,可以随时添加其他检查。

import inspect
def update(src):
    result = []
    cprev = inspect.currentframe().f_back
    #print(cprev.f_code.co_names)
    for v in cprev.f_code.co_names[1:]:
        if src is cprev.f_locals[v]: continue
        if v in src:
            result.append(src[v])
        else:
            raise NameError(v + " has no source for update")
    return result

用法如下:

src={'a': 1, 'b': 2, 'c': 3}
a,b,c = update(src)

答案 9 :(得分:0)

@glglgl 的答案不是最多投票的,那个答案对我有用,

solution1={'variable': np.array([75, 74]), 'function': 0}

def dict_get(d, *k):
    for i in k:
        yield d[i]


variables, obj_func = dict_get(solution1, 'variable', 'function')

a, b=variables

print(a)

参考:@glglgl