我对 Python assert 语句的使用有不同的看法,我希望你能告诉我为什么我错了
I have a different opinion about my usage of the Python assert statement and I would like you to tell me why I am wrong
请听我说完。我知道 assert
是如何工作的。
对于上下文,我想到的一些应用程序和用法涉及通过 GUI 进行数学优化,因此这些函数可以被调用数亿次。
assert
语句在优化模式 (-O
) 中被禁用,因此依赖它被认为是不好的做法(阅读:capital sin)根据大多数人的意见(也许这不仅仅是一种意见,我不知道)。
假设我有以下计算圆面积的函数:
def area_circle(r):
return 3.141592654 * (r**2)
是的,我知道,没有文档字符串。这是一个玩具示例。为了确保 radius
是 int
或 float
,我会这样做:
def area_circle(r):
assert isinstance(r, (int, float), 'TypeError: Expected int or float, not ' + type(r).__name__
return 3.141592654 * (r**2)
我对它的看法可能应该让我公开处决,因为我认为它是一个很好的功能,允许我在开发时进行一些输入检查等,但是当我达到生产就绪状态时,我可以在优化模式下禁用那些不必要的代码部分。如果我的系统测试涵盖导致使用 area_circle
的工作流,那么我个人不想看到 raise
语句,因为它们只是浪费。
那么,如何在不使用 assert
的情况下以不减慢应用程序的方式进行集成系统测试?
编辑 1
这里有两条额外的信息需要考虑:
- 没有外部数据来源,一切都来自
图形用户界面;
- 输入验证直接在 GUI 中完成
您的论点似乎是 assert
语句非常适合调试(确实如此),并且 您 在 您的用例中 可以对每个代码路径进行充分的单元测试,您可以在生产过程中自信地关闭它们以获得性能,并且您现在怀疑 every 可能使用显式 raise
语句。
嗯,并不是每个代码都可以测试到那个程度。有代码 "at the frontlines" 必须在运行时 进行输入验证 ,并且必须使用显式检查和显式 raise
语句。很高兴 you 有这样一种情况,您的后端代码不需要担心输入验证,因为您有足够的信心认为这是在前一层处理的。在这种情况下,一定不要进行输入验证并关闭 assert
语句。这并不意味着在任何情况下都是可能的。例如,您的前端仍然需要明确的运行时检查,并且可能会在内部明确 raise
错误。
raise
语句适用于当您的程序遇到无法处理的 异常情况 时。您的代码向远程服务器发出 HTTP 请求,该服务器以 [=16=] 响应。这是特殊情况。这不是您的代码的快乐路径。这是你的代码无法处理的情况,它只能在运行时发生,没有办法通过单元测试来防止这种情况。在这种情况下,raise
抛出异常是一件非常明智的事情。
请听我说完。我知道 assert
是如何工作的。
对于上下文,我想到的一些应用程序和用法涉及通过 GUI 进行数学优化,因此这些函数可以被调用数亿次。
assert
语句在优化模式 (-O
) 中被禁用,因此依赖它被认为是不好的做法(阅读:capital sin)根据大多数人的意见(也许这不仅仅是一种意见,我不知道)。
假设我有以下计算圆面积的函数:
def area_circle(r):
return 3.141592654 * (r**2)
是的,我知道,没有文档字符串。这是一个玩具示例。为了确保 radius
是 int
或 float
,我会这样做:
def area_circle(r):
assert isinstance(r, (int, float), 'TypeError: Expected int or float, not ' + type(r).__name__
return 3.141592654 * (r**2)
我对它的看法可能应该让我公开处决,因为我认为它是一个很好的功能,允许我在开发时进行一些输入检查等,但是当我达到生产就绪状态时,我可以在优化模式下禁用那些不必要的代码部分。如果我的系统测试涵盖导致使用 area_circle
的工作流,那么我个人不想看到 raise
语句,因为它们只是浪费。
那么,如何在不使用 assert
的情况下以不减慢应用程序的方式进行集成系统测试?
编辑 1
这里有两条额外的信息需要考虑:
- 没有外部数据来源,一切都来自 图形用户界面;
- 输入验证直接在 GUI 中完成
您的论点似乎是 assert
语句非常适合调试(确实如此),并且 您 在 您的用例中 可以对每个代码路径进行充分的单元测试,您可以在生产过程中自信地关闭它们以获得性能,并且您现在怀疑 every 可能使用显式 raise
语句。
嗯,并不是每个代码都可以测试到那个程度。有代码 "at the frontlines" 必须在运行时 进行输入验证 ,并且必须使用显式检查和显式 raise
语句。很高兴 you 有这样一种情况,您的后端代码不需要担心输入验证,因为您有足够的信心认为这是在前一层处理的。在这种情况下,一定不要进行输入验证并关闭 assert
语句。这并不意味着在任何情况下都是可能的。例如,您的前端仍然需要明确的运行时检查,并且可能会在内部明确 raise
错误。
raise
语句适用于当您的程序遇到无法处理的 异常情况 时。您的代码向远程服务器发出 HTTP 请求,该服务器以 [=16=] 响应。这是特殊情况。这不是您的代码的快乐路径。这是你的代码无法处理的情况,它只能在运行时发生,没有办法通过单元测试来防止这种情况。在这种情况下,raise
抛出异常是一件非常明智的事情。