在python中进行逻辑参数检查

时间:2011-01-19 22:01:57

标签: python parsing parameters typechecking

我不确定我的问题是否有一个具体的答案,但无论如何。我正在编写一个包含大量参数的函数,每个参数可以是None,也可以是有限的值范围。由于我不相信用户给我好的输入,我必须检查每个参数的类型,如果它是正确的类型(或None),那么我想看看它是否在正确的范围。这意味着我有很多像这样的代码:

# size
if isinstance(size, str):
    if size in range(4):
        self.data[uid]['size'] = int(size)
    else:
        warnings.warn("ID %s: illegal size %s" % (uid, size))
        self.data[uid]['size'] = None
elif size == None:                                
    self.data[uid]['size'] = None
else:
    warnings.warn("ID %s: illegal size %s" % (uid, str(size)))
    self.data[uid]['size'] = None

等。由于这变得越来越重复,我想知道是否有可以自动执行此操作的库,抛出异常/警告并减少代码冗余。

由于

4 个答案:

答案 0 :(得分:1)

我同意上述内容:假设size属于正确类型,如果不是,则引发异常(或返回错误)。

但是,当您处理可能引发异常的输入时,有一个有用的模式:包装输入引发的任何异常,使它们包含输入。例如,你会得到:

ParseError: while parsing 'number = foo': ValueError: invalid literal for int() with base 10: 'foo'

代码看起来像这样:

try:
    parse(input)
catch Exception, e:
    raise ParseError("while parsing %r: %r" %(input, e)), None, sys.exc_info()[2]

raise的第三个参数将使用原始回溯,因此堆栈跟踪将指向实际导致错误的行(例如size = int(value)),而不是调用{{1 }}

答案 1 :(得分:1)

我会改写这个:

# size
if isinstance(size, str):
    if size in range(4):
        self.data[uid]['size'] = int(size)
    else:
        warnings.warn("ID %s: illegal size %s" % (uid, size))
        self.data[uid]['size'] = None
elif size == None:                                
    self.data[uid]['size'] = None
else:
    warnings.warn("ID %s: illegal size %s" % (uid, str(size)))
    self.data[uid]['size'] = None
像这样:

if size in ["0", "1", "2", "3"]: # alternative: if size in map(str, range(4)):
    self.data[uid]['size'] = int(size)
else:
    if size != None:
        warnings.warn("ID %s: illegal size %s" % (uid, size))
    self.data[uid]['size'] = None    

我真诚地不喜欢的是使用isinstance(size, str)(因为它很容易打破ducktyping,所以在Python中通常不赞成使用显式类型检查。

这就是为什么你不能在Python中轻松找到一个库以自动化类型检查的原因:它违背了该语言的核心意图。

答案 2 :(得分:1)

  

我想知道是否会有   将自动化的库,   抛出异常/警告并减少   代码冗余。

我使用formencode这样的东西。它似乎只是用于解析HTML表单,但它会愉快地解析并验证您传递给它的任何内容。您可以定义一次验证所有输入的模式类。

答案 3 :(得分:0)

如果您的项目是库,而您的“用户”是另一个开发人员,请不要这样做。最多,用断言替换你的测试:

assert 0 <= int(size) <= 4, "size must be between 0 and 4"

这样,当用户提供错误的输入时,他们会立即听到它 - 然后他们就有责任做好准备。


如果您的项目是一个应用程序而您的“用户”是我的祖母,您需要自己进行验证:崩溃不是一个可接受的响应。但是,在这种情况下,您应该更多地了解可能的输入(例如,它来自文本框,因此它只能是一个字符串)。

我的建议是如上编码您的实用程序功能并单独执行验证(即UI层)。很少有实用程序/库函数应该验证和覆盖(即使有警告)该值:它需要阻止调用者/用户进一步获取,直到他们已经把事情做好。