解构 - 绑定字典内容

时间:2010-06-02 06:17:29

标签: python sorting dictionary

我试图'解构'字典并将值与变量名称关联起来。像

这样的东西
params = {'a':1,'b':2}
a,b = params.values()

但由于字典未订购,因此无法保证params.values()将按(a, b)的顺序返回值。有没有一个很好的方法来做到这一点?

14 个答案:

答案 0 :(得分:25)

比Jochen的建议更少重复的一种方法是使用辅助函数。这样可以灵活地按任意顺序列出变量名称,并且只解构dict中的变量名称的子集:

pluck = lambda dict, *args: (dict[arg] for arg in args)

things = {'blah': 'bleh', 'foo': 'bar'}
foo, blah = pluck(things, 'foo', 'blah')

此外,您可以对键进行排序并获取值,而不是joaquin的OrderedDict。唯一的捕获是您需要按字母顺序指定变量名称并解构dict中的所有内容:

sorted_vals = lambda dict: (t[1] for t in sorted(dict.items()))

things = {'foo': 'bar', 'blah': 'bleh'}
blah, foo = sorted_vals(things)

答案 1 :(得分:13)

Python只能“解构”序列,而不是字典。因此,要编写您想要的内容,您必须将所需的条目映射到正确的序列。就我自己而言,我能找到的最接近的匹配是(不是很性感):

a,b = [d[k] for k in ('a','b')]

这也适用于发电机:

a,b = (d[k] for k in ('a','b'))

以下是一个完整的例子:

>>> d = dict(a=1,b=2,c=3)
>>> d
{'a': 1, 'c': 3, 'b': 2}
>>> a, b = [d[k] for k in ('a','b')]
>>> a
1
>>> b
2
>>> a, b = (d[k] for k in ('a','b'))
>>> a
1
>>> b
2

答案 2 :(得分:13)

from operator import itemgetter

params = {'a': 1, 'b': 2}

a, b = itemgetter('a', 'b')(params)

与其使用复杂的lambda函数或字典理解功能,不如使用内置库。

答案 3 :(得分:8)

也许你真的想做这样的事情?

def some_func(a, b):
  print a,b

params = {'a':1,'b':2}

some_func(**params) # equiv to some_func(a=1, b=2)

答案 4 :(得分:7)

如果您害怕使用本地词典所涉及的问题,并且您更愿意遵循原始策略,则可以使用python 2.7和3.1 collections.OrderedDicts中的有序词典来恢复订单中的词典项目。他们是第一次插入

答案 5 :(得分:4)

为什么没有人发布最简单的方法?

params = {'a':1,'b':2}

a, b = params['a'], params['b']

答案 6 :(得分:3)

这是另一种方法,类似于destructuring assignment在JS中的工作方式:

params = {'b': 2, 'a': 1}
a, b, rest = (lambda a, b, **rest: (a, b, rest))(**params)

我们要做的是将params字典解包成键值(使用**)(例如在Jochen's answer中),然后我们将这些值取入了lambda签名,并根据键名进行了分配-还有一个好处-我们还会得到lambda签名中不是的字典,如果您有的话:

params = {'b': 2, 'a': 1, 'c': 3}
a, b, rest = (lambda a, b, **rest: (a, b, rest))(**params)

在应用lambda之后,其余变量现在将包含: {'c':3}

用于从字典中删除不需要的键。

希望这会有所帮助。

答案 7 :(得分:3)

警告1:,如文档中所述,不能保证在所有Python实现中都可以使用:

CPython实现细节:此函数依赖于Python堆栈框架支持 在解释器中,并不能保证在所有实现中都存在 Python。如果在没有Python堆栈框架支持的实现中运行 此函数返回None。

警告2:此函数的确使代码更短,但可能与Python尽可能明确的哲学相矛盾。而且,尽管您可以创建一个类似的功能,而不是键,但可以使用属性,但它不能解决John Christopher Jones在评论中指出的问题。这只是您可以真的愿意做的一个演示!

def destructure(dict_):
    if not isinstance(dict_, dict):
        raise TypeError(f"{dict_} is not a dict")
    # the parent frame will contain the information about
    # the current line
    parent_frame = inspect.currentframe().f_back

    # so we extract that line (by default the code context
    # only contains the current line)
    (line,) = inspect.getframeinfo(parent_frame).code_context

    # "hello, key = destructure(my_dict)"
    # -> ("hello, key ", "=", " destructure(my_dict)")
    lvalues, _equals, _rvalue = line.strip().partition("=")

    # -> ["hello", "key"]
    keys = [s.strip() for s in lvalues.split(",") if s.strip()]

    if missing := [key for key in keys if key not in dict_]:
        raise KeyError(*missing)

    for key in keys:
        yield dict_[key]
In [5]: my_dict = {"hello": "world", "123": "456", "key": "value"}                                                                                                           

In [6]: hello, key = destructure(my_dict)                                                                                                                                    

In [7]: hello                                                                                                                                                                
Out[7]: 'world'

In [8]: key                                                                                                                                                                  
Out[8]: 'value'

此解决方案使您可以选择某些键,而不是全部,例如JavaScript。用户提供的字典也很安全

答案 8 :(得分:2)

好吧,如果你想在课堂上这些,你可以随时这样做:

class AttributeDict(dict):
    def __init__(self, *args, **kwargs):
        super(AttributeDict, self).__init__(*args, **kwargs)
        self.__dict__.update(self)

d = AttributeDict(a=1, b=2)

答案 9 :(得分:2)

尝试

d = {'a':'Apple', 'b':'Banana','c':'Carrot'}
a,b,c = [d[k] for k in ('a', 'b','c')]

结果:

a == 'Apple'
b == 'Banana'
c == 'Carrot'

答案 10 :(得分:0)

我不知道这是好风格,但是

locals().update(params)

会做到这一点。然后,您可以ab以及params dict中可用的相应局部变量。

答案 11 :(得分:0)

基于@ShawnFumo的答案,我想到了这一点:

def destruct(dict): return (t[1] for t in sorted(dict.items()))

d = {'b': 'Banana', 'c': 'Carrot', 'a': 'Apple' }
a, b, c = destruct(d)

(请注意字典中项目的顺序)

答案 12 :(得分:0)

由于字典是guaranteed to keep their insertion order in Python >= 3.7,这意味着如今这样做是完全安全和惯用的:

params = {'a': 1, 'b': 2}
a, b = params.values()
print(a)
print(b)

输出:

1
2

答案 13 :(得分:0)

使用 Python 3.10,您可以:

d = {"a": 1, "b": 2}

match d:
    case {"a": a, "b": b}:
        print(f"A is {a} and b is {b}")

但它增加了两个额外的缩进级别,并且您仍然需要重复键名。