可以有太多断言(在Python中)?

可以有太多断言(在Python中)?,python,validation,assert,Python,Validation,Assert,最近,我在几乎每一个函数中添加了断言,以验证每一个输入,作为一种穷人的类型检查替代品,或者防止自己在开发过程中意外输入格式错误的数据。比如说, def register_symbol(self, symbol, func, keypress=None): assert(isinstance(symbol, basestring)) assert(len(symbol) == 1) assert(callable(func)) assert(keypress is

最近,我在几乎每一个函数中添加了
断言
,以验证每一个输入,作为一种穷人的类型检查替代品,或者防止自己在开发过程中意外输入格式错误的数据。比如说,

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

然而,我担心这与duck打字的想法背道而驰,我可能会太过火或不必要地限制自己。你会有太多的断言语句吗?什么时候是停止的好时机?

我只使用
assert
s,如果它们提供的诊断效果远远好于我在其他情况下得到的错误消息。你的第三个断言

assert(callable(func))
可能就是这样一个断言的例子——如果
func
不可调用,您将在与实际错误所在的代码行完全不同的代码行中收到错误消息,并且不可调用对象如何在
self.symbols\u map
中结束可能并不明显。我之所以写“may”,是因为这取决于代码的其余部分——如果这是更新
self.symbols\u map
的唯一地方,那么断言也可能是不必要的

第一个和最后一个断言肯定反对duck类型的想法,第二个断言是多余的。如果
symbol
不是长度为1的字符串,那么
self.symbols\u map[symbol]
很可能会引发
KeyError
,因此不需要断言

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


您可能应该编写一组好的单元测试——它们将比断言有用得多,并且可能使几乎所有的断言都是多余的。

代码中的断言远不如单元测试有用。多做后者,少做前者。

请注意,每当Python生成优化字节码时,assert语句都会被剥离!因为在大多数生产环境中都是这样,所以assert语句可能不用于验证输入。
事实上,我得出的结论是,如果我不能依靠他们被处决,我就不能用他们做任何事情。因此,如果我需要检查某些条件,我会使用“if…raise…”,如果我只想测试我的代码,我会编写单元测试。

旁注:你应该使用duck类型(不要检查类型,检查可用方法等“能力”)。而且,返回是完全没有必要的。真正的问题是:它对你有帮助还是使你的工作更困难。如果大量断言有助于跟踪错误,请在代码中进行大量断言。如果你需要静态输入,为什么选择Python作为你的项目?@Niklas我喜欢返回。它让我内心快乐:D@Secator我真的很喜欢Python的动态性,但有时我希望它更严格一点,这样我就可以更早地发现错误。这只是我试图调和这种冲动。不过,我并不真正想要完全的静态类型。@deffect:Heh,这是一个参数:P顺便说一句,我同意Secator,如果您需要类型安全性,但不想错过动态元素,请尝试Haskell或Scala或类似的方法。在Python中,你根本无法接近它们的类型安全级别。嗯,如果
symbols\u map
是一个dict,它不应该产生
KeyError
@NiklasB.:你能进一步解释一下吗?@Sven:对不起,我的意思是行
self.symbols\u map[symbol]=(func,keypress)如果
symbol
未满足OP似乎已放置在键上的约束条件,则
不会引发错误。@NiklasB:您完全正确,但我不是从您上次的评论中得到的。:)