如何在Python中将传入的字典解包到函数命名空间?
在我的工作中,我经常需要把一些参数分组,以便更方便地使用:
d1 = {'x':1,'y':2}
d2 = {'a':3,'b':4}
我通常是通过传入多个字典来实现这个目的。大多数时候,我直接使用传入的字典,也就是说:
def f(d1,d2):
for k in d1:
blah( d1[k] )
在某些函数中,我需要直接访问这些变量,这样就变得有些麻烦;我其实希望这些变量能在本地的命名空间中。也就是说,我想做一些像这样:
def f(d1,d2)
locals().update(d1)
blah(x)
blah(y)
但是,locals() 返回的字典更新并不一定能真正更新命名空间。
这里有一种明显的手动方法:
def f(d1,d2):
x,y,a,b = d1['x'],d1['y'],d2['a'],d2['b']
blah(x)
return {'x':x,'y':y}, {'a':a,'b':b}
这样做会导致每个函数的参数列表重复三次。这可以通过一个装饰器来自动化:
def unpack_and_repack(f):
def f_new(d1, d2):
x,y,a,b = f(d1['x'],d1['y'],d2['a'],d3['b'])
return {'x':x,'y':y}, {'a':a,'b':b}
return f_new
@unpack
def f(x,y,a,b):
blah(x)
blah(y)
return x,y,a,b
这样做会导致装饰器重复三次,每个函数再加上两次,所以如果你有很多函数,这样做会更好。
有没有更好的方法呢?也许可以用 eval?谢谢!
11 个回答
7
假设你字典里的所有键都可以当作标识符,那么你可以这样做:
adict = { 'x' : 'I am x', 'y' : ' I am y' }
for key in adict.keys():
exec(key + " = adict['" + key + "']")
blah(x)
blah(y)
10
如果你觉得用 d.variable
这种写法比 d['variable']
更好,你可以把字典放进一个几乎不复杂的“bunch”对象里,像这样:
class Bunch:
def __init__(self, **kw):
self.__dict__.update(kw)
这样做并不能完全把字典里的内容放到本地命名空间里,但如果你给对象起个短名字,效果会很接近。
38
你可以随时把一个字典作为参数传递给一个函数。比如说,
dict = {'a':1, 'b':2}
def myFunc(a=0, b=0, c=0):
print(a,b,c)
myFunc(**dict)