我应该在python函数/方法上做多少输入验证?

时间:2008-12-15 05:39:52

标签: python validation

我对他们编写的Python中有多少前期验证感兴趣。

以下是一些简单函数的例子:

def factorial(num):
    """Computes the factorial of num."""

def isPalindrome(inputStr):
    """Tests to see if inputStr is the same backwards and forwards."""

def sum(nums):
    """Same as the built-in sum()... computes the sum of all the numbers passed in."""

在开始计算之前检查输入值有多彻底,如何进行检查?如果输入有问题(例如,在同一模块中定义了BadInputException),是否会抛出某种专有异常?你刚刚开始计算,并认为如果传入了错误的数据(例如,“asd”到factorial),它会在某个时刻抛出异常吗?

当传入的值应该是一个容器时,你不仅检查容器,还检查其中的所有值吗?

像factorial这样的情况怎么样,传入的内容可以转换为int(例如浮点数),但这样做可能会失去精度?

8 个答案:

答案 0 :(得分:10)

assert什么是绝对必要的。

重要:什么是绝对必不可少的。有些人过度测试。

def factorial(num):
    assert int(num)
    assert num > 0

不完全正确。长期也是合法的可能性。

def factorial(num):
    assert type(num) in ( int, long )
    assert num > 0

更好,但仍然不完美。许多Python类型(如有理数或类似数字的对象)也可以在良好的阶乘函数中工作。很难断言一个对象具有类似于整数的基本属性,而不是过于具体,并且不需要考虑未来的未考虑过的类。

我从未为各个功能定义唯一的例外。我为重要的模块或包定义了一个唯一的例外。但是,通常只有Error类或类似的东西。这样应用程序会说except somelibrary.Error,e:这就是你需要知道的全部内容。细粒度的例外变得挑剔和愚蠢。

我从未这样做,但我可以看到可能需要的地方。

assert all( type(i) in (int,long) for i in someList ) 

但是,通常,普通的Python内置类型检查工作正常。他们发现几乎所有特殊情况几乎一直都很重要。当某些东西不是正确的类型时,Python会引发一个始终指向正确代码行的TypeError。

顺便说一句。如果我绝对确定该函数会被滥用,我只会在设计时添加断言。有时候,当我的单元测试以不明显的方式失败时,我会添加断言。

答案 1 :(得分:6)

对于sum,factorial等计算,pythons内置类型检查会很好。计算将结束upp为类型调用 add mul 等,如果它们中断,它们将抛出正确的异常。通过强制执行您自己的检查,您可能会使其他工作输入无效。

答案 2 :(得分:5)

我正在尝试编写文档字符串,说明期望和接受的参数类型,我不会在我的函数中明确地检查它。

如果有人想要将我的功能与任何其他类型一起使用,那么他有责任检查他的类型是否模仿我的类型,我接受得足够好。也许你的阶乘可以用一些自定义类似长度来获得你想不到的东西?或者你的总和可以用来连接字符串?为什么要通过类型检查禁止它?反正它不是C.

答案 3 :(得分:4)

我基本上尝试将变量转换为应该变量,并且如果失败则传递或抛出相应的异常。

def factorial(num):
    """Computes the factorial of num."""
    try:
        num = int(num)
    except ValueError, e:
        print e
    else:
        ...

答案 4 :(得分:2)

这取决于我正在写什么,以及输出是如何产生的。 Python没有其他OO语言的公共/私人保护。相反,有些惯例。例如,外部代码应该只调用没有下划线作为前缀的对象方法。

因此,如果我正在编写模块,我将验证任何不是由我自己的代码生成的内容,即对公共可访问方法/函数的任何调用。有时,如果我知道验证是昂贵的,我可以使用kwarg进行切换:

def publicly_accessible_function(arg1, validate=False):
  if validate:
    do_validation(arg1)
   do_work

内部方法可以通过assert语句进行验证,当代码退出开发并投入生产时,可以完全禁用该语句。

答案 5 :(得分:1)

我几乎从不强制执行任何检查,除非我认为有人可能认为他们可以传递一些会产生完全疯狂结果的X.

另一次我检查的是当我接受一个参数的几种类型时,例如一个接受列表的函数,可能会接受一个任意对象并将其包装在一个列表中(如果它还不是一个列表)。因此,在这种情况下,我检查类型 - 不强制执行任何操作 - 只是因为我希望函数在使用方式上具有灵活性。

答案 6 :(得分:0)

只需要检查你是否有一个强制你的单元测试失败。

还要考虑“EAFP”......这是Python方式!

答案 7 :(得分:0)

关于另一种语言如何处理它的一些观点可能会增加一些价值。对于Perl,我记得使用这个模块 - http://search.cpan.org/dist/Params-Validate/从开发人员那里卸载了很多参数验证。我在python中搜索类似的内容并遇到了这个问题:http://www.voidspace.org.uk/python/validate.html我还没有尝试过。但我认为,针对整个代码库中验证参数的标准方法,可以在整个团队中预先设置参数验证期望。