你有太多的断言(用Python)吗?

时间:2012-03-08 20:34:22

标签: python validation assert

最近,我几乎每一个函数都添加了asserts来验证每个输入,作为穷人替代类型检查的一种方式,或者防止我在开发时意外输入格式错误的数据。例如,

def register_symbol(self, symbol, func, keypress=None):
    assert(isinstance(symbol, basestring))
    assert(len(symbol) == 1)
    assert(callable(func))
    assert(keypress is None or type(keypress) is int)
    self.symbols_map[symbol] = (func, keypress)
    return

然而,我担心这与鸭子打字的想法背道而驰,而且我可能会过分夸大自己或者不必要地限制自己。你有没有太多的断言陈述?什么时候停下来?

3 个答案:

答案 0 :(得分:7)

我只使用assert,如果它们提供的诊断程度远远超过我将得到的错误消息。你的第三个断言

assert(callable(func))

可能是这样一个断言的一个例子 - 如果func不可调用,你将在一个完全不同的代码行上得到一个错误消息,而不是实际的错误,并且可能不是很明显不可调用的对象最终在self.symbols_map。我写“可能”,因为这取决于你的其余代码 - 如果这是self.symbols_map更新的唯一地方,那么断言也可能是不必要的。

第一个和最后一个断言肯定是反对鸭子打字的想法,而第二个断言是多余的。如果symbol不是长度为1的字符串,则self.symbols_map[symbol]可能会提升KeyError,因此不需要断言。

最后一个断言也是错误的 - type(keypress)不能是None,并且应该使用isinstance()进行类型检查。可能存在非常专业的应用程序,您不能允许子类型,但应该使用type(x) is int而不是type(x) == int执行检查。检查None应由x is None完成,而不是type(x) is NoneType

你应该写一组好的单元测试 - 它们比断言更有用,并且可能使你的几乎所有断言都多余。

答案 1 :(得分:3)

代码中的断言并不像单元测试那样有用。做后者的更多,而不是前者。

答案 2 :(得分:2)

请注意,只要Python生成优化的字节码,就会剥离断言语句!由于大多数生产环境都是这种情况,因此断言语句不能用于验证输入。 事实上,我得出的结论是,如果我不能依赖它们被执行,我根本无法使用它们。因此,如果我需要检查一些条件,我会使用“if ... raise ...”,如果我只是想测试我的代码,我会编写单元测试。