Python输入有效性和使用断言

Ret*_*sam 3 python validation assert

我正在尝试对我的python代码执行良好的输入有效性检查,但我也希望它简洁.也就是说,我想要的解决方案就是这个:

def some_func(int_arg, str_arg, other_arg):
    try:
        int_arg = int(int_arg)
    except TypeError, ValueError
        logging.error("int_arg must respond to int()")
        raise TypeError
    try:
        if str_arg is not None:
            str_arg = str(str_arg) 
    except TypeError
        logging.error("Okay, I'm pretty sure this isn't possible, bad example")
        raise TypeError
    if other_arg not in (VALUE1, VALUE2, VALUE3):
        logging.error("other arg must be VALUE1, VALUE2, or VALUE3")
        raise TypeError
Run Code Online (Sandbox Code Playgroud)

这只是太多的代码和很多空间,只需要检查3个参数.

我目前的做法是:

def some_func(int_arg, str_arg, other_arg):
    try:
        int_arg = int(int_arg)  #int_arg must be an integer
        str_arg is None or str_arg = str(str_arg)  #str_arg is optional, but must be a string if provided
        assert other_arg in (VALUE1, VALUE2, VALUE3)
    catch TypeError, ValueError, AssertionError:
        logging.error("Bad arguments given to some_func")
        throw TypeError
Run Code Online (Sandbox Code Playgroud)

我失去了我的日志消息的特异性,但在我看来,这更简洁,更诚实.

我特别想知道的一件事是使用断言语句.我已经读过,不鼓励使用断言作为检查输入有效性的方法,但我想知道这是否是使用它的合法方式.
如果没有,是否有类似的方法来执行此检查(或通常进行此验证)仍然非常简洁?

Kos*_*Kos 9

你可以发明一个装饰器,为你验证参数.

这就是语法的样子:

@validate(0, int)
@validate(1, str, logMessage='second argument must respond to str()')
@validate(2, customValidationFunction)
def some_func(int_arg, str_arg, other_arg):
    # the control gets here only after args are validated correctly
    return int_arg * str_arg
Run Code Online (Sandbox Code Playgroud)

这是验证装饰工厂的一个简单实现.

def validate(narg, conv, logMessage = None):
    def decorate(func):
        def funcDecorated(*args):
            newArgs = list(args)
            try:
                newArgs[narg] = conv(newArgs[narg])
            except Exception, e:
                # wrong argument! do some logging here and re-raise
                raise Exception("Invalid argument #{}: {}".format(narg, e))
            else:
                return func(*newArgs)

        return funcDecorated
    return decorate
Run Code Online (Sandbox Code Playgroud)

是的,这里有一些函数嵌套,但这一切都有意义.让我解释:

  • 装饰器需要一个函数并返回另一个函数
  • 我们希望validate(narg, converter)成为一个函数,它接受一些设置并返回一个特定的装饰器(decorate),它根据这些设置运行
  • decorate然后被用于装饰给定功能(func通过创建一个新的功能需要一些位置参数)funcDecorated,是以相同的参数func(*args)并且被写入输入功能方面func以及初始设置narg,conv.

实际验证发生在funcDecorated中,其中......

  • 获取输入参数列表,
  • 通过验证和/或转换它来替换第n个参数(无论如何conv),
  • func使用更改的参数列表调用输入.

为了对多个参数执行此操作,我们validate使用不同的参数多次应用.(它可以重写它只装饰一次,但IMO看起来更清楚.)

请参阅实际操作:http://ideone.com/vjgIS


请注意,conv可以采取行动......

  • 作为验证函数(返回它接收的任何内容,但如果它无效则抛出)
  • 作为转换函数(返回转换后的值,如果无法转换则抛出)

请注意,此实现不处理关键字参数.