动态定义具有不同签名的函数

Lan*_*aru 4 python dynamic

我想要完成的事情:

dct = {'foo':0, 'bar':1, 'baz':2}
def func(**dct):
    pass
#function signature is now func(foo=0, bar=1, baz=2)
Run Code Online (Sandbox Code Playgroud)

但是,**语法在扩展dict(我想要做的事情)和声明一个包含关键字参数的参数(我不想做的事情)之间显然会发生冲突.

这可能吗?

Sha*_*hin 5

基于我对您的需求的解释 - 您希望动态定义一个具有与dict运行时提供的内容相匹配的签名的函数- 这里有两个问题使得它不切实际.

  1. 如果参数是在运行时定义的,那么你的函数如何引用变量?您是否计划在运行时构建函数体?
  2. dicts是无序的,因此您无法可靠地使用它们来定义位置参数

我怀疑这是一个XY问题.如果你能解释你想要实现的目标,那么也许我们可以提供更好的帮助.

但是,假设您尝试使用dict一种方法来分配默认关键字参数来实现这一点,那就是使用装饰器.例如:

def defaultArgs(default_kw):
    "decorator to assign default kwargs"
    def wrap(f):
        def wrapped_f(**kwargs):
            kw = {}
            kw.update(default_kw)  # apply defaults
            kw.update(kwargs)  # apply from input args
            f(**kw)  # run actual function with updated kwargs
        return wrapped_f
    return wrap
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用此装饰器将默认关键字参数分配给仅需要关键字参数的函数:

defaults = {'foo':0, 'bar':1, 'baz':2}

@defaultArgs(defaults)
def func(**kwargs):
    print kwargs  # args accessible via the kwargs dict
Run Code Online (Sandbox Code Playgroud)

结果:

func()  # prints {'baz': 2, 'foo': 0, 'bar': 1}
func(foo=2)  # prints {'baz': 2, 'foo': 2, 'bar': 1}

params = {'bar':1000, 'hello':'world'}
func(**params)  # prints {'baz': 2, 'foo': 0, 'bar': 1000, 'hello': 'world'}
Run Code Online (Sandbox Code Playgroud)

请注意,您将无法使用位置参数:

func(1, 2, 3)   # raises TypeError
Run Code Online (Sandbox Code Playgroud)