使用Python装饰器强制执行标准方法签名

时间:2014-12-04 21:02:57

标签: python decorator python-decorators

我有一个包含许多功能的库。我希望与基本方法模式保持一致。我希望所有方法都将上下文作为第一个参数和关键字arg,默认为0。

library_function(context, ..., default=0)

有没有办法可以使用python decorators转

bobs_function(foo, bar=None)

bobs_library_function(context, foo, bar=None, default=0)

这样做的目的是提供声明库函数的简写。而不是每次都明确添加上下文和默认值。

2 个答案:

答案 0 :(得分:1)

如果只允许在包装函数中传递关键字参数,则可以使其工作:

import functools

def lib(fn):
    @functools.wraps(fn)
    def wrapped(context, default=0, **kwargs):
        print context, default
        return fn(**kwargs)
    return wrapped

@lib
def bobs_function(foo, bar=None):
    print foo
    print bar


bobs_function('context', foo='foo', bar='bar', default='default')

打印:

context default
foo
bar

答案 1 :(得分:-2)

我越是看起来和想到这一点,我越相信答案是否定的。

我希望能够从bobs函数内部访问上下文和默认值。希望是我可以提供一个方便的速记,以确保我编写遵循惯例的方法签名。

问题在于我必须提前声明bob_function所采用的参数。如果它需要一个位置参数,那么添加一个新的位置参数会使一切变得混乱。

所以我第一次想到

@library_function
def bobs_function(foo, bar=None):
     ....

神奇地改变方法签名是行不通的。

我的下一个想法是扭转它

@library_function(foo, bar=None)
def bobs_function(*args, **kwargs):
    ...

但这在语法上是不正确的。而且我留下了不愉快的结果,不得不把我的变量从args和费用中捕获。

总结一下我的问题。如果我想使用上下文我必须传入它。我不能修改bobs_function的实际声明参数,所以我可以传递上下文的唯一方法是使用* args ** kwargs,这是远比打字更令人不愉快

bobs_library_function(context, foo, bar=None, default=0)

开头。