我试图'解构'字典并将值与变量名称关联起来。像
这样的东西params = {'a':1,'b':2}
a,b = params.values()
但由于字典未订购,因此无法保证params.values()
将按(a, b)
的顺序返回值。有没有一个很好的方法来做到这一点?
答案 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)
会做到这一点。然后,您可以a
,b
以及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}")
但它增加了两个额外的缩进级别,并且您仍然需要重复键名。