我不确定我的问题是否有一个具体的答案,但无论如何。我正在编写一个包含大量参数的函数,每个参数可以是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
等。由于这变得越来越重复,我想知道是否有可以自动执行此操作的库,抛出异常/警告并减少代码冗余。
由于
答案 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层)。很少有实用程序/库函数应该验证和覆盖(即使有警告)该值:它需要阻止调用者/用户进一步获取,直到他们已经把事情做好。