我正在尝试“解构”一个字典,并将其键与变量名称关联起来,以使用其值。就像这样:
params = {'a':1,'b':2}
a,b = params.values()
但是由于字典是无序的,不能保证params.values()
按照(a, b)
的顺序返回值。有没有一种好的方法可以做到这一点?
我正在尝试“解构”一个字典,并将其键与变量名称关联起来,以使用其值。就像这样:
params = {'a':1,'b':2}
a,b = params.values()
但是由于字典是无序的,不能保证params.values()
按照(a, b)
的顺序返回值。有没有一种好的方法可以做到这一点?
from operator import itemgetter
params = {'a': 1, 'b': 2}
a, b = itemgetter('a', 'b')(params)
可以使用内置库,而不是复杂的lambda函数或字典推导式。
attrgetter
,它适用于对象属性(obj.a
)。这与JavaScript有很大不同,JavaScript中obj.a === obj["a"]
。 - John Christopher JonesKeyError
异常。 - Tasawar Hussaina,b = [d[k] for k in('a','b')]
这样的形式更加自然/可读(这种形式更为常见)。这仍然是一个有趣的答案,但不是最直接的解决方案。 - cglacetget_id = itemgetter(KEYS)
之类的东西,然后稍后使用serial,code,ts = get_id(document)
更简单。不可否认,您必须熟悉高阶函数,但Python通常非常适合它们。例如,请参见装饰器@contextmanager
的文档。 - John Christopher Jones为什么没有人发布最简单的方法?
params = {'a':1,'b':2}
a, b = params['a'], params['b']
b, a = params["b"], params["a"]
。 - Glenn Mohammadpluck = lambda dict, *args: (dict.get(arg, -1) for arg in args)
things = {'blah': 'bleh', 'foo': 'bar'}
foo, blah = pluck(things, 'foo', 'blah')
sorted_vals = lambda dict: (t[1] for t in sorted(dict.items()))
things = {'foo': 'bar', 'blah': 'bleh'}
blah, foo = sorted_vals(things)
lambda
分配给变量,最好使用正常的 def
函数语法。 - Arthur Taccaoperator
中的 itemgetter
。 :) - John Christopher JonesPython只能“解构”序列,而不能解构字典。因此,为了编写您想要的内容,您需要将所需条目映射到适当的序列。就我个人而言,我找到的最接近的匹配是(不是很引人注目):
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
params = {'b': 2, 'a': 1}
a, b, rest = (lambda a, b, **rest: (a, b, rest))(**params)
params = {'b': 2, 'a': 1, 'c': 3}
a, b, rest = (lambda a, b, **rest: (a, b, rest))(**params)
a, b = (lambda a, b, **_): (a, b))(**params)
也许你真的想做这样的事情?
def some_func(a, b):
print a,b
params = {'a':1,'b':2}
some_func(**params) # equiv to some_func(a=1, b=2)
a = data['a'], b = data['b']
。 - Richard Rast**params
等同于 Python 的 命名 参数传递,其整个目的是不关心顺序。some_func(a=1, b=2)
== some_func(b=2, a=1)
。 - Beni Cherniavsky-Paskin{ "key": [ { "inner_key": var } ] }
那样,而是需要一层一层地解构——外部函数def f1(key):
,然后在其中[ item ] = key
,然后内部函数def f2(inner_key): ...
。 - Beni Cherniavsky-Paskin如果您担心使用locals字典所涉及的问题,并且更喜欢遵循原始策略,那么Python 2.7和3.1中的有序字典collections.OrderedDicts可以让您按照最初插入的顺序检索字典项。
使用Python 3.10,您可以执行以下操作:
d = {"a": 1, "b": 2}
match d:
case {"a": a, "b": b}:
print(f"A is {a} and b is {b}")
但它会增加两个额外的缩进级别,并且你仍然需要重复键名。
from ... import
语句允许我们拆解和绑定一个对象的属性名。当然,它只适用于sys.modules
字典中的对象,因此可以使用以下技巧:
import sys, types
mydict = {'a':1,'b':2}
sys.modules["mydict"] = types.SimpleNamespace(**mydict)
from mydict import a, b
一个更为严肃的黑客技巧是编写上下文管理器来加载和卸载模块:
with obj_as_module(mydict, "mydict_module"):
from mydict_module import a, b
__getattr__
方法直接指向字典的 __getitem__
方法,上下文管理器还可以避免使用 SimpleNamespace(**mydict)
。参见此答案以获取实现和一些扩展思路。sys.modules
字典为感兴趣的字典,并在不使用 from
的情况下进行 import a, b
。__getattr__
:) - decorator-factorysys.modules
是非常冒险的。如果一个函数可以从多个线程中调用,那么在其中使用任何这些方法也是有风险的;在顶层使用更为安全。但是,非常聪明的观察——确实,import...from
语法具有解构的特性 :-) - Beni Cherniavsky-Paskin警告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'
let {a, b} = params
。它可以提高可读性,完全符合你想要讨论的任何禅意。 - Andylet {a: waffles} = params
。即使你习惯了它,也需要几秒钟才能弄清楚。 - John Christopher Jones