如何在Python中将传入的字典解包到函数命名空间?

34 投票
11 回答
62425 浏览
提问于 2025-04-15 16:58

在我的工作中,我经常需要把一些参数分组,以便更方便地使用:

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)

撰写回答