传递具有无效键=值对的kwargs来运行

时间:2011-08-27 20:59:03

标签: python

以下代码:

def f(a=1):
    pass

kwargs = {}
kwargs['a'] = 1
kwargs['b'] = 2

f(**kwargs)

(正确)引发异常:

Traceback (most recent call last):
  File "tt.py", line 8, in <module>
    f(**kwargs)
TypeError: f() got an unexpected keyword argument 'b'

有没有办法,使用functools或其他方法来解决这个问题,并找出函数没有使用哪些参数,以便能够将它们传递给另一个函数?例如,我可能有另一个功能:

def g(a=None, b=None):
    pass

我想打电话,例如。

g(**kwargs)

但我只希望传递b,因为a已在前一个功能中“用完”。

现在我知道这不是理想的编码,但有些情况下它可以派上用场,而且实际上很容易向用户解释,例如: “其他参数将传递给f,任何未传递给f的参数都将传递给g”。

3 个答案:

答案 0 :(得分:5)

我有点惊讶你提出这个问题,并担心你正在做一些你可能会后悔的事。

您是否尝试使用相同的字典调用不同的方法,并提供所有参数组合? 如果是这样,则处理这种情况所需的复杂性不应该在被调用的方法中处理,而是在调用代码中处理,例如,通过将kwargs定制到要调用的特定方法:

def f(a=1):
    pass

call_tailored_args(f, kwargs)

辅助函数将实现如下:

import inspect

def tailored_args(f, kwargs):
    relevant_args = {k: v in kwargs if k in inspect.getargspec(f).args}
    f(**relevant_args)

答案 1 :(得分:4)

这是你的意思吗?

def g(**kwargs):
    a=kwargs.pop('a',None)    
    b=kwargs.pop('b',None)
    print(a,b)
def f(**kwargs):
    a=kwargs.pop('a',None)
    print(a)
    g(**kwargs)

kwargs = {'a':1,'b':2}

f(**kwargs)
# 1
# (None, 2)

答案 2 :(得分:1)

您可以使用装饰器删除额外的kwargs键:

def remove_args(fx):
    def wrap(**kwargs):
        kwargs2 = copy.copy(kwargs)

        ret = None
        done = False

        while not done:
            try:
                ret = fx(**kwargs2)
                done = True
            except TypeError, ex:
                key = re.findall("\'(\w+)\'", ex.message)[0]
                del kwargs2[key]              # Remove offending key
                # print "%s removing %s" % (fx.__name__, key)

        return ret

    return wrap


@remove_args
def f1(a=1):
    return "f1-ret"

@remove_args
def f2(b=1):
    return "f2-ret"

kwargs = {"a": 1, "b": 2, "c": 3}

print f1(**kwargs)
print f2(**kwargs)