在 Python 中进行函数参数检查
在 StackOverflow 看到这个问题:How to check arguments of the function?,正好我自己也遇到了这个问题。 于是顺手把这个问题和最佳回答翻译过来。
提问者Oleg Tarasenko;最佳答案作者Alex Martelli
Question
我有一个这样定义的函数:
|
|
我想检查参数 a
和 b
,使其不等于某些特定值,该怎么做?
比如我想确保它们的值不是空字符串(''
或者 ' '
)。
我有想过下面这种方法。
|
|
然后检查,确保参数不是 ''
或者 ' '
。
但在此例中它会检查 None
值(译注:这一句我没看懂),而我想避免这个。
Answer
典型的方法:
|
|
或者你可以根据自己的需求,对严重的问题发出警告或者引发异常。
比起在你需要检查参数的函数中直接使用,这部分检查更应该剥离到单独的函数里。 (前者将会成为粘在你程序逻辑中的一团检查代码——还是把它们分开为好)
|
|
要进行检查的函数就可以改为:
|
|
也可以把它写成一个装饰器来使用。
|
|
下面我们让这些检查用的代码更加“骨肉分离”(译注:想了好久才憋出这个词 去耦合(感谢@比尔盖子 的提醒)。
不过注意,除非你有很多函数需要进行这种检查,否则这完全是矫枉过正。==|||
)
参数名的自省(由于 inspect
模块,这一点才变得可行)用在装饰器中要比直接用在目标函数中复杂得多。
这也是为什么在此例中我最喜欢的设计是避免使用装饰器(简洁是极好的 ;-)
)。
编辑——在提问者的要求下(虽然并没有说明原因),说明如何实现一个参数检查的装饰器。
(在 Python 2.6
及更早的版本中的)主要问题是要在封装中构造一种等效于 locals()
调用产生的映射关系。
但是——如果你在使用 Python 2.7
,inspect.getcallargs
就可以帮你实现。于是问题变得简单多了,这样一来装饰器似乎值得一用。(如果你在使用 2.6 或者更早的版本,我仍然推荐避免使用装饰器来实现,针对这种特殊的场景,其复杂性会大幅提高。)
以下就是在 Python 2.7
环境下需要的所有代码(前文中定义的 check_arguments
函数可以重用):
|
|
在 Python 2.7
之前版本中实现的难度完全来自于如何实现等效的 inspect.getcallargs
——所以,我希望,如果你需要使用这类装饰器的话,去官方网站下载 Python 2.7
安装吧。(这样,你将可以得到额外的便利,并且能有更长的技术支持周期,毕竟 2.7 是 Python 2.x
分支的最后一个版本了。)