我应该总是测试每个功能的参数类型吗?

时间:2015-09-16 07:50:10

标签: python validation types

我有一个参数intTup的函数。该功能由用户调用,因此输入可能是错误的,所以我想验证它。

特别是intTup必须:

  • 是一个元组
  • 长度为3
  • 仅包含整数

因此,只要执行该函数,就会检查这些属性:

def myFunc(intTup)
    if type(intTup) is not tuple:
        print("intTup       = ", intTup)
        print("type(intTup) = ", type(intTup))
        raise Exception('In parameter intTup : should be a tuple of float')
    elif (len(h) != 3) :
        print("intTup      = ", intTup)
        print("len(intTup) = ", len(intTup))
        raise Exception('In parameter intTup : should contain three atoms')
    elif [int]*len(intTup) == map(type,intTup):
        print("intTup       = ", intTup)
        print("type(intTup) = ", map(type,intTup))
        raise Exception('In parameter h : all atoms should be ints')
    # Some actual code follow these tests

当然经常遇到这种类型的检查:只要函数允许包含n个类型为t的tuple类型的参数,就必须运行类似的检查。因此,我应该定义一个函数checkTuple(tupleToTest, shouldBeLen, shouldBeType)来自动执行这些检查吗?或者我应该留下它是怎么回事?你如何继续你的脚本?

5 个答案:

答案 0 :(得分:4)

没有。在Python中你使用“鸭子类型”:如果某些东西像鸭子一样走路,像鸭子一样呱呱叫,像鸭子一样游泳,它就会被鸭子识别出来。

换句话说,使用Python,我们相信是您所做的,它定义了您的内容

这意味着你应该依赖于对象的属性,而不是它的类型。在您的情况下,您只需使用输入,即使用“包含int s的3元组”,并处理异常。

另请参阅:isinstance considered harmful

答案 1 :(得分:2)

也许你应该考虑EAFP。

  

比获得许可更容易请求宽恕。这种常见的Python编码风格假设存在有效的键或属性,并且如果假设被证明是错误则捕获异常。这种干净和快速的风格的特点是存在许多try和except语句。该技术与许多其他语言(如C。

)共有的LBYL风格形成对比

docs

尝试处理用户输入,如果由于某种原因失败,则引发异常。在大多数强调防止错误的其他语言中,你通常不会这样做,但对于python,通常使用EAFP原则。

换句话说,不要验证。

答案 2 :(得分:1)

如果要进行运行时类型检查,使用没有静态类型检查的语言有什么意义?你的问题的答案是:不;你不应该总是检查参数约束。如果你想拥有这种控制,那么就有更好的工具。在某些情况下,您可能需要键入check,例如在接受来自用户或外部进程的输入时,但您不希望始终执行此操作。

答案 3 :(得分:1)

如果你真的(真的吗?)必须打破鸭脸,你可以如下断言参数的有效性:

def myFunc(intTup):
    """intTup is a tuple of size 3"""
    assert(isinstance(intTup, tuple)), "not a tuple"
    assert(len(intTup) == 3), "not length 3"

比宽容更容易请求宽恕:)

您可以查看warnings module

答案 4 :(得分:0)

你可以让装饰师检查是否

     def validate(func):
         def f(*args, **kwargs): 
             if args[0] is not tuple or len(args[0])! =3:
                 raise Exception("invalid parameter") 
             return func(*args, **kwargs) 
         return f