我正在寻找一种优雅的方法来将 Python 字典中的一些值提取到本地值中。
与此等效的东西,但对于更长的值列表和更长的键/变量名称来说更清晰:
d = { 'foo': 1, 'bar': 2, 'extra': 3 }
foo, bar = d['foo'], d['bar']
我最初希望得到类似以下的东西:
foo, bar = d.get_tuple('foo', 'bar')
我可以轻松编写一个不错的函数:
def get_selected_values(d, *args):
return [d[arg] for arg in args]
foo, bar = get_selected_values(d, 'foo', 'bar')
但我一直怀疑还有其他内置方法。
你可以做类似的事情
foo, bar = map(d.get, ('foo', 'bar'))
或
foo, bar = itemgetter('foo', 'bar')(d)
这可能会节省一些打字时间,但本质上与您正在做的事情相同(这是一件好事)。
有点可怕,但是:
globals().update((k, v) for k, v in d.iteritems() if k in ['foo', 'bar'])
请注意,虽然这是可能的 - 这是您真正不想做的事情,因为您会污染应该留在
dict
本身内部的名称空间...
好吧,如果你提前知道名字,你就可以按照你的建议去做。
如果您事先不知道它们,请坚持使用字典 - 这就是它们的用途。
如果您坚持,替代方案是:
varobj = object()
for k,v in d.iteritems(): setattr(varobj,k,v)
之后,键将成为
varobj
上的变量。
从
locals()
写入当地人在过去并不总是有效。 (下面代码的全局版本应该可以在早期版本中使用。)
TL;博士:
locals().update(options)
过滤功能示例:
options = dict(one=1, _two=2)
def update_locals(options, filter_prefix=None):
print(vars())
if filter_prefix:
locals().update(
{k:v for k,v in options.items()
if not k.startswith(filter_prefix)}
)
else:
locals().update(options) # all
print(vars(), '\n')
update_locals(options)
update_locals(options, '_')
输出:
{'options': {...}, 'filter_prefix': None}
{'options': {...}, 'filter_prefix': None, 'one': 1, '_two': 2}
{'options': {...}, 'filter_prefix': '_'}
{'options': {...}, 'filter_prefix': '_', 'one': 1}
您可能不需要过滤,因此可以简化该部分。
如果你正在寻找跨 Python 版本的优雅和性能,遗憾的是我认为你不会得到比以下更好的了:
unpack = lambda a,b,c,**kw: (a,b,c) # static
d = dict( a=1, b=2, c=3, d=4, e=5 )
a,b,c = unpack(**d)
工作示例:
>>> unpack = lambda a,b,c,**kw: (a,b,c)
>>> d = dict( a=1, b=2, c=3, d=4, e=5, f=6, g=7 )
>>> a,b,c = unpack(**d)
>>>
>>> unpack(**d)
(1, 2, 3)
您还可以解压原本会被丢弃的差异:
>>> unpackextra = lambda a,b,c,**kw: (a,b,c,kw)
>>> a,b,c,extra = unpackextra(**d)
>>>
>>> unpackextra(**d)
(1, 2, 3, {'f': 6, 'd': 4, 'e': 5, 'g': 7})
虽然参数是静态的,所以用例应该特定于您的意图。 ;)
>>> unpack2 = lambda a,b,c,d,e,f,**kw: (a,b,c,d,e,f) # static
>>>
>>> unpack2(**d)
(1, 2, 3, 4, 5, 6)
>>>
优雅的解决方案:
d = { "foo": 123, "bar": 456, None: 789 }
foo, bar, baz = d.values() # 123, 456, 789
请注意,未使用键,因此请确保变量的顺序正确,即它们必须与键插入映射的顺序匹配(自 Python 3.6 起保证了此顺序)。如果对订购有疑问,请使用其他方法。