最近,我几乎每一个函数都添加了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
然而,我担心这与鸭子打字的想法背道而驰,而且我可能会过分夸大自己或者不必要地限制自己。你有没有太多的断言陈述?什么时候停下来?
答案 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 ...”,如果我只是想测试我的代码,我会编写单元测试。