忘记返回函数的结果:如何防止这个bug?

时间:2012-04-08 22:48:10

标签: python coding-style python-3.x static-analysis

我有时会忘记函数中的return result

def f(*args):
  # do stuff
  result = # an expression
  # oops forgot to return result

由于None是我的应用程序中的有效值,因此不会在调用者中引发任何异常甚至任何警报。当然,我正在努力小心。但我想知道是否有一些巧妙的方法来警告我任何没有明确返回值的函数。

也许正则表达式我可以通过我的代码来查找这样的情况。或者一些代码检查工具(希望在Windows环境下可用)。

我甚至在考虑使用这样的装饰器:

def requires_return(func):
  def new_func(*args, **kwargs):
    result = func(*args, **kwargs)
    if result is None:
      print('Warning: {} may be missing a return statement'.format(func.__name__))
    return result

但这不起作用,因为:

  1. 许多错误警报:每次函数实际返回None。我不能在我的应用程序中停止使用None而不在其他地方创建非常丑陋的代码。

  2. 无论如何,为每个函数添加一个装饰器似乎都非常难看。

  3. 请注意,我确实有功能,我故意没有return语句。我倾向于保持一定的命名约定,这使我可以轻松区分它们。 (具体来说,以get_开头的每个函数都必须有一个return语句。)

4 个答案:

答案 0 :(得分:4)

我建议不要养成做

的习惯
def something():
    ...
    result = ...
    return result

而只是做:

def something():
    ...
    return ...

除此之外,默认情况下返回None是99%的有用功能。

答案 1 :(得分:4)

简答

总之:unittest

这不是您应该尝试使用生产代码解决的问题。一组好的测试将解决您的问题。

单元测试101

您应该真正了解单元测试是什么,作为快速参考,请记住单元测试是关于测试您的API。

还有一种称为TDD(测试驱动开发)的东西,它是在实际代码之前编写测试的实践。所以程序员为一段不存在的代码编写测试,测试显然失败,程序员转到生产代码,编写他的函数,运行测试,如果测试通过,他继续。

一开始养成编写测试的习惯有点困难,但确实有所回报。

为什么单位测试

我无法看到如何通过正确的测试来错过回报。

  

“由于None是我的应用程序中的有效值,因此不会在调用者中引发任何异常甚至是任何警报。”

返回None的做法是破坏您的API。单元测试是确切的解决方法。

  

如何防止此错误?

阻止此错误的方法是使用TDD

如果您首先编写测试,那么在它甚至成为一个错误之前,99.9%肯定能够捕获此错误。

注意:我知道这不是您正在寻找的答案,但单元测试是正确的工具。不使用result变量或将装饰器附加到每个函数都无法解决您的问题。

答案 2 :(得分:3)

Pylint有时会遇到这种错误。特别是如果您分配给result但从不使用它:

pylint zorg.py
************* Module zorg
W0612:  5:zorg: Unused variable 'result'

然而,它没有捕获你在片段中构建result然后忘记返回它的情况(因为那时变量不是“未使用”)。

根据许多其他事情,pylint通过静态类型分析可能会发现无法返回值。

答案 3 :(得分:0)

最好是防止而不是治愈 - 这意味着你应该真正学会在必要时返回价值的习惯。您也可以直接使用return statement代替result = statement; return result