使用类装饰器限制函数参数类型Args和KWargs

时间:2016-06-10 06:31:02

标签: python parameters

我想要一个易于使用的装饰器类,可用于强制某些参数为预定义类型,以免引发错误。问题是我必须指定每个变量两次,每个args一个,kwargs一个。即使使用默认参数也是如此,前提是原始函数中没有单个splat参数。

简化为:

class ParamConstraint:
    def __init__(self, *args, error=TypeError, **kwargs):
        self.args = args
        self.kwargs = kwargs
        self.error = error

    def __call__(self, function):
        def wrap(*args, **kwargs):
            for (arg, constraint) in zip(args, self.args):
                if not isinstance(arg, constraint):
                    raise self.error(
                        "Value '{}' is not of type '{}'.".format(arg, constraint.__name__)
                    )
            for kwarg in self.kwargs:
                if kwarg in kwargs:
                    assert isinstance(kwargs[kwarg], self.kwargs[kwarg])
            return function(*args, **kwargs)
        return __import__("functools").wraps(function)(wrap)

这很容易使用。假设我想要一个将数字乘以2的函数,但我只想要整数,而不是浮点数。我可以用:

@ParamConstraint(int)
def foo(x):
    return x*2

print(foo(5))  # => prints 10
print(foo(x=5.0))  # => prints 10.0
print(foo(5.0))  # => raises TypeError

现在,我可以通过将位置和非位置参数传递到函数中来防止这种情况,但一段时间后它变得非常乏味。例如,我必须为3个参数写出6个约束:

@ParamConstraint((int, float), int, FunctionType, value=(int, float), count=int, func=FunctionType):
def foo(value, count, func):
    for _ in range(count):
        value = func(value)
    return value

理想情况下,我应该能够通过KWarg传递它而不提供任何位置参数。但是,这不起作用,因为我无法找出原始函数的位置参数是什么。我曾使用inspect模块无效。

我该如何补救?

0 个答案:

没有答案