强制特定函数签名

Force specific function signatures

我刚发现自己在写这样的代码:

def register(self, *,  # * enforces keyword-only parameters
             key_value_container:dict=None,    # legal parameter set #1
             key:str=None, value=None):        # legal parameter set #2

    # enforce one of the parameter sets
    if not ((key_value_container is not None and 
             key is None and value is None) or
            (key is not None and value is not None and 
             key_value_container is None)):
        raise TypeError('provide (key_value_container) or (key/value')

    # handle each legal parameter setf
    if key_value_container is not None:
        for _k, _s in key_value_container.items():
            self.register(_k, _s)
    else:
        do_something_with(key, value)

我的目标是拥有方法 register() 的两个签名:它应该采用一个 key 和一个 value 或带有多个键和值的容器,例如dict.

参数中的 * 至少迫使我提供命名参数,但没有必要提供 给定数量的参数 甚至 一组给定的参数.

当然我可以(应该)提供两种不同名称和签名的方法,而不是一种。

但万一我想(必须)提供一个 method/function 具有多个参数语义 - 使它可见并强制执行它的最佳方法是什么?

详细:

为了避免样板代码,您可以这样做:编写额外的函数来指定不同的签名。然后有一个 redirect 辅助函数,它根据参数匹配的签名将参数从主函数发送到附加函数。

还是不是特别优雅。如果对此进行概括,您还需要考虑如何处理 None 是您可能想要传递的有效参数的情况。

from inspect import getargspec
class Eg(object):
    def register(self, key_value_container=None, key=None, value=None):
        return redirect(locals(), [self.register_dict, self.register_single])

    def register_dict(self, key_value_container=None):
        print('register dict', key_value_container)

    def register_single(self, key=None, value=None):
        print('register single', key, value)

def redirect(params, functions):
    provided = {k for k, v in params.items() if v is not None}
    for function in functions:
        if set(getargspec(function).args) == provided:
            return function(**{k: params[k] for k in provided if k != 'self'})
    raise TypeError('wrong configuration provided') 
    # This error could be expanded to explain which signatures are allowed       

a = Eg()
a.register(key='hi', value='there')
a.register(key_value_container={'hi': 'there'})