Python 输入有效性和使用断言

标签 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

这只是检查 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

我失去了我的日志消息的特殊性,但在我看来,这更加简洁,而且老实说更具可读性。

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

最佳答案

您可以发明一个装饰器来为您验证参数。

语法是这样的:

@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

这是验证装饰器工厂的简单实现。

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

是的,这里有一些函数嵌套,但都是有道理的。让我解释一下:

  • 装饰器是接受一个函数并返回另一个函数的东西
  • 我们想要validate(narg, converter)成为一个接受一些设置并返回根据这些设置运行的特定装饰器 ( decorate ) 的函数
  • decorate然后用于装饰一个给定的函数(func),该函数通过创建一个新函数 funcDecorated 接受一些位置参数。采用与 func 相同的参数( *args ) 并根据输入函数 func 编写以及初始设置 narg , conv .

实际验证发生在 funcDecorated 内部,它...

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

为了对几个参数执行此操作,我们应用 validate多次使用不同的参数。 (可以将其重写为仅装饰一次,但这样看起来更清晰 IMO。)

查看实际效果:http://ideone.com/vjgIS


请注意 conv可以行动...

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

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

关于Python 输入有效性和使用断言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12154178/

相关文章:

java - 为什么断言不应该用于公共(public)方法中的参数检查?

python - 如何验证文本字段是否具有我输入的值?

python - 为什么在将属性更改为引用外部函数后不传递 self?

python - opencv、BGR2HSV 会产生大量伪影

python - 以浮点秒数增加初始时间值?

python - 在 Python 中丢弃具有最大容量的 FIFO 队列?

django - 表单集验证时出现 ManagementForm 数据丢失错误

java - 如何在 Jenkins 上验证来自 config.jelly 的表单?

javascript - 简洁的 Angular 表单验证

java - 使用 assertTrue() 验证 selenium 中文本的存在