【问题标题】:Validity check of function arguments in Python: should every function do it?Python中函数参数的有效性检查:每个函数都应该这样做吗?
【发布时间】:2018-10-31 06:38:37
【问题描述】:
每个 Python 函数(或方法)都应该检查其参数的有效性吗?
不仅仅是类型,如果值在有效范围内,尺寸是否符合预期等?
或者可以只拥有简单地期望其他函数、程序员等具有“成人式”良好行为的函数?只需在文档字符串中提及预期内容,并在面向用户的函数中检查用户输入参数的有效性吗?
在“私有”方法的情况下,在我看来我们不需要检查有效性,但是其他方法/功能呢?
如果我们对此过于严格并检查所有内容,代码会不会充满无聊的装饰器类型代码?可以吗?
【问题讨论】:
标签:
python
function
validation
methods
arguments
【解决方案1】:
Python 鼓励使用鸭式打字或“请求宽恕比请求许可更容易”(EAFP),这意味着您应该假设您的论点是正确的,如果不正确,请适当地处理这种情况。
我们假设“如果它像鸭子一样走路和说话,那么它一定是鸭子”。看这里:
class Duck:
def quack(self):
return 'quack!'
class Person:
def quack(self):
return 'Hey there!'
d = Duck()
p = Person()
def make_it_quack(duck):
return duck.quack()
print(make_it_quack(d))
print(make_it_quack(p))
如您所见,这两种类型都有效。这是故意行为。如果您遇到未定义该方法的内容,您将按预期获得AttributeError。解决这个问题的方法是使用异常处理:
try:
print(make_it_quack(d))
print(make_it_quack(p))
print(make_it_quack('hello world'))
except AttributeError:
print('object must have a "quack" method')
说了这么多,我个人并不总是坚持下去。例如,如果我不能保证我的对象的类型,那么我将使用if isinstance(x, Y) 之类的东西来正确地指导代码。如果没有,则返回try except。
您可以自行决定选择哪一种使您的代码更简洁并适合您的情况。对此有一些建议,例如“始终使用 try/except for IOErrors”(这是有原因的)。
【解决方案2】:
我认为这可以普遍应用,不仅适用于 Python,而且我认识的所有人都始终遵循这样一种理念,即如果可能发生的最坏情况是错误消息,则假设输入将是正确的。
除非你的代码正在运行一个任务,即使你已经尽可能安全地编写它,它仍然可以破坏某些东西,在这种情况下总是检查。
【解决方案3】:
我见过很多不同的方法。最极端的一个是文档字符串包含参数类型和范围的正式声明(也是返回值)。应用程序在运行时根据这些文档字符串检查参数,如果出现问题则抛出异常。这是使用元编程实现的,并且可以在生产运行时禁用。
它不再是真正的 Python,ducktyping 也不可能了。它更像是一种没有帮助编译器的静态类型语言。您仍然必须等到它在运行时中断。
我还看到了不进行任何检查而只运行综合单元测试的应用程序。如果它们通过了,则假定参数也正常。
就我个人而言,我也使用单元测试涵盖了大部分内容,但在关键部分我使用断言。我还特别注意接收用户输入的方法。
希望有帮助