在设计Python API时,抛出异常或返回false / None等更加Pythonic吗?

时间:2013-11-20 13:36:18

标签: python api exception class-design

我正在使用基于Python的API,其中有许多函数可用于查询事物,例如doesPointExistfindPointcanCreateNewPoint等,其中否定结果会引发异常。这使得代码更加混乱,填充了try / catch语句,而不是直接将结果用作布尔值。

由于我不是Python专家,我想知道这个设计是不是Pythonic?我没有在标准库中看到过这种设计,所以我假设P​​ython API中的这种异常使用是不受欢迎的?

5 个答案:

答案 0 :(得分:6)

听起来像设计糟糕的API。

  • 函数doesPointExist应返回TrueFalse,当该点不存在时,它不应引发异常。
  • 当找不到任何对象时,函数findPoint应返回Point个对象或None
  • 功能canCreateNewPoint应返回TrueFalse出于类似原因。

例外是针对例外情况。

答案 1 :(得分:6)

API设计有点艺术。函数的名称应该表明它的行为方式,包括设置用户期望。名为findPoint的函数意味着搜索可能会失败,因此不存在此类点的情况并非例外,并且可能会返回None来表示结果。但是,名为getPoint的函数会向我暗示它始终可以返回请求的点。失败是出乎意料的,并且需要提出异常。

答案 2 :(得分:3)

我不同意你不会在标准库中找到它。例如,"abc".index("d")引发ValueError,许多库自由地引发异常。

我会说这取决于失败行动的后果。

  • 如果调用者可以使用返回的值而不进行更改,我将返回一个空值(或False,如果它是肯定的或没有问题的话。)
  • 如果通话失败,我会提出异常。例如,如果findPoint()通常返回调用者想要使用的Point对象,{{1}}可能会这样做。

答案 3 :(得分:2)

1,我建议对特定情况使用异常,因此在常见情况下不需要对它们进行测试。

2,您应该阅读有关您的职能名称的指南PEP8 Naming Conventions

答案 4 :(得分:2)

这不是Python独有的。其他答案都很好,但只有一些额外的想法不适合评论:

  • 当您不想(或不需要)检查结果时,您可以使用例外。在这种模式下,您只需执行此操作,如果某处出现错误,则会抛出异常。摆脱显式检查可以缩短代码,并且在获得异常时仍然可以获得良好的调试信息,因此这很常见。这是上面的EAFP(更容易请求宽恕而不是许可)。
  • 如果您想检查结果,请使用返回代码。如果故障不会总是干净地失败,或者有助于在复杂的代码流中进行调试,则有时需要进行显式检查。这有时被称为LBYL(在你跳跃之前看)风格。

在Python中,与大多数解释语言一样,由于开销太高,异常相对便宜,因此在Python中使用EAFP比在C ++中更常见,比如C ++,其中开销较低,异常(相对)更多昂贵。

请注意,函数可能都会返回值可能会抛出异常。

在您的示例中,像doesPointExist这样的函数意味着用户在尝试某事之前实际上想要验证访问权限。这是LBYL。抛出异常作为结果值是EAFP编程风格的一部分,并且对于这个函数没有意义 - 如果你想要那个样式,你就不会检查,你只会这样做,并在点上时捕获异常不存在。

然而,即使在这里也有假设 - 你给出了一个有效的观点。对于该点是否存在,该函数返回True / False是正常的,而如果某个不是一个点的东西被传递给它则抛出异常。