【问题标题】:Python Exception guidelines explanationPython 异常指南解释
【发布时间】:2021-09-01 14:40:42
【问题描述】:

在 Google 的 Python 样式指南文档中,他们提到了以下内容:

请注意,文档中没有提到 ValueError 的提升 字符串的“Raises:”部分,因为它不适合保证 这种对 API 滥用的特定行为反应。

为什么不合适?这是否意味着一开始就不应该像这样使用 ValueError ?

def connect_to_next_port(self, minimum: int) -> int:
"""Connects to the next available port.

Args:
  minimum: A port value greater or equal to 1024.

Returns:
  The new minimum port.

Raises:
  ConnectionError: If no available port is found.
"""
if minimum < 1024:
  # Note that this raising of ValueError is not mentioned in the doc
  # string's "Raises:" section because it is not appropriate to
  # guarantee this specific behavioral reaction to API misuse.
  raise ValueError(f'Min. port must be at least 1024, not {minimum}.')
port = self._find_next_open_port(minimum)
if not port:
  raise ConnectionError(
      f'Could not connect to service on port {minimum} or higher.')
assert port >= minimum, (
    f'Unexpected port {port} when minimum was {minimum}.')
return port

【问题讨论】:

  • 如果你想防止错误的值,你可以作为你的函数的作者做任何你想做的事情,只要它被记录在案。您可以很好地选择返回None 或负值,让调用者决定在这种情况下该怎么做。但是恕我直言,最好(a)询问该代码的作者是否想确定他在这种特定情况下的意思(b)以基于意见的方式结束此问题

标签: python exception


【解决方案1】:

ConnectionError 可以是根据记录的用法使用该函数的结果。

然而,ValueError 只是公然违反函数前提条件的结果。您已经被警告minimum &gt;= 1024 必须为真。您不需要记录违反该警告的后果。

例如,您不需要try 语句来处理ValueError;您可以在调用函数之前检查参数的值以避免它。 (在这种情况下请求宽恕比请求许可更容易。)

您确实需要一个try 语句来处理ConnectionError,因为无法预测它可能会发生。为了知道可能会引发ConnectionError,这需要记录在案。


从具有静态类型检查的整体语言的角度来看,不同之处在于您可以通过使用适当的 argument 类型来避免错误,而通过使用适当的 类型可以避免错误返回类型。在类似 Haskell 的伪代码中考虑偏函数。

type ValidPort = Int
connect_to_next_port :: ValidPort -> ValidPort
connect_to_next_port = ...

但不仅仅是任何Int 都是有效端口;只有 1024 到 65535 之间的整数(TCP/IP 中的端口是 16 位值)。所以想象我们有一种方法来定义一个受限类型,我们可以用

消除ValueError
type ValidPort = { x :: Int | 1024 <= x <= 65535 }
connect_to_next_port :: ValidPort -> ValidPort
connect_to_next_port = ...

但我们可能找不到要返回的端口。我们没有引发异常,而是返回 Maybe ValidPort 类型的内容,您可以将其视为包含 ValidPort 类型值和 None 值(大致对应于 Haskell 中的 Nothing)的包装器。

type ValidPort = { x :: Int | 1024 <= x <= 65535 }
connect_to_next_port :: ValidPort -> Maybe ValidPort
connect_to_next_port = ...

要说的是,我们记录了可以编码为返回类型的异常,而不是可以通过适当的参数类型消除的异常。

【讨论】:

  • 感谢您的详细见解!现在它比我最初阅读它时更有意义。这些天我喜欢学习这些小东西,谢谢。
猜你喜欢
  • 1970-01-01
  • 2013-03-15
  • 1970-01-01
  • 1970-01-01
  • 2014-10-25
  • 1970-01-01
  • 1970-01-01
  • 2023-01-11
  • 1970-01-01
相关资源
最近更新 更多