保持函数调用签名对于接受另一个函数参数的超集的函数是一致的

时间:2016-05-25 18:22:43

标签: python python-2.7

我有一个函数(foo),它是另一个函数(bar)的便利函数包装器。 foo调用bar,然后在输出上执行另外几项任务。例如:

def bar(bar_arg, bar_kw=None):
    #do some stuff
    return ret

def foo(bar_arg, foo_arg, bar_kw=None, foo_kw=None):
    ret = bar(bar_arg, bar_kw)
    ret.some_method(foo_arg, foo_kw=foo_kw)

我希望foo的调用签名包含来自bar的关键字和参数,以便检查foo的用户知道他们可以通过什么,但是,我想避免自bar因为它来自的包更新并且其参数列表很长而导致foo趋于改变时,我自己维护完整的参数列表。由于bar始终使用bar接受的参数和关键字的完整列表来调用foo,因此我不会发现我应该自己维护列表。

有没有办法根据bar的呼叫签名为foo建立呼叫签名?另外,有没有办法捕获字典或命名空间中foo的输入,以便我可以轻松地将bar使用的参数和关键字与bar使用的参数和关键字分开?

注意,我知道* args和** kwargs。但是,它们使函数签名不明确,并且不会告知用户允许哪些参数和关键字参数。

编辑:我应该注意,我的用例比这个例子复杂得多。被调用的外部函数(matplotlib.colorbar.ColorbarBase)是foo。调用函数(foo)是绘图类的类方法,该类在我自己的许多应用程序中使用,其他应用程序可能在将来使用。 ColorbarBase创建一个颜色条,然后根据C不接受的其他参数和关键字对颜色条执行其他工作。

2 个答案:

答案 0 :(得分:1)

由于bar()包裹调用foo()构造函数的ColorbarBase,因此请在foo()调用周围编写一个装饰器。装饰器在调用foo()之前对传入bar的参数进行修改。

from matplotlib import pyplot
import matplotlib as mpl


def bar(f):
    def wrapper(*args, **kwargs):
        # Change args, kwargs for calling foo()
        f(*new_args,**new_kwargs)
        return
return wrapper


@bar
def foo(*new_args, **new_kwargs):
    return mpl.colorbar.ColorbarBase(*new_args, **new_kwargs)

例如,以下内容向调用者返回一个ColorbarBase对象,提供一组初始参数,然后由bar()修改。通过这种方式,foo()的呼叫签名基于bar()的呼叫签名。

fig = pyplot.figure(figsize=(8, 3))
ax1 = fig.add_axes([0.05, 0.80, 0.9, 0.15])
cmap = mpl.cm.cool
norm = mpl.colors.Normalize(vmin=5, vmax=10)

ret = foo(ax1, 
          cmap=cmap,
          norm=norm,
          orientation='horizontal')

答案 1 :(得分:0)

我认为最好的选择是省略foo。只需使用用户需要的简单构建块,即可让API简短而甜蜜,以便他们快速了解如何使用您的库。程序员可以很容易地创建他们真正想要的便利功能,而不会被你认为他们想要的功能分散注意力。

如果您的实际功能比他们在问题中看起来更复杂,那么请更新问题以显示该问题。现在,程序员只需编写

即可明确而明确
my_bar = bar(bar_arg, bar_kw)
my_bar.some_method(foo_arg, foo_kw=foo_kw)

为自己。任何读者都知道究竟发生了什么,并且不必解析长参数列表,并且额外的代码行也没问题。