如何解决在 `with` 语句中启动多个上下文管理器时使用 `and` 而不是 `,`
在编写单元测试时,我经常使用以下模式:
with self.subTest("Invalid input") and self.assertRaises(ValueError):
...
但直到今天我才知道according to python specs,I should be using ,
:
with self.subTest("Invalid input"),self.assertRaises(ValueError):
...
并且规范中没有提到 and
作为一个选项。然而,这些测试似乎总是运行良好。
在这里使用 and
时可能会出现哪些问题?为什么它似乎通常与 ,
的工作方式相同?
相关:Multiple variables in a 'with' statement?
解决方法
您拥有的是带有 and
运算符的表达式。如果 and
运算符为 falsey,则返回其第一个操作数,否则返回其第二个操作数。假设 self.subTest(...)
返回一些真实,您的代码等价于:
ctx = self.subTest("Invalid input") and self.assertRaises(ValueError)
with ctx: ...
相当于:
self.subTest("Invalid input")
ctx = self.assertRaises(ValueError)
with ctx: ...
或者:
self.subTest("Invalid input")
with self.assertRaises(ValueError): ...
因此,充其量,您所拥有的内容可能会产生误导。最坏的情况是它是一个错误,因为没有使用 subTest
的上下文管理器。
如果 self.subTest
返回 falsey 值,则永远不会执行 self.assertRaises(...)
,这将是您测试中的明显错误。
加上@deceze 的出色回答,您可以很容易地观察到这一点:您只需要创建自己的上下文管理器。
运行以下代码:
class C:
def __init__(self,id):
self.id = id
def __enter__(self):
print(f'Entering {self.id}')
return self
def __exit__(self,exc_type,exc_value,traceback):
print(f'Exiting {self.id}')
return self
with C(0),C(1): print('with statement 1')
print()
with C(2) and C(3): print('with statement 2')
您会看到打印了以下输出:
Entering 0
Entering 1
with statement 1
Exiting 1
Exiting 0
Entering 3
with statement 2
Exiting 3
发生的情况是,对于第一个 with
语句,两个值按顺序输入,然后以相反的顺序退出(这些是 Python 的 with
语句的语义)。但是在第二个 with
中,只有第二个项目被处理(进入然后退出) - 因为第一个被 and
运算符丢弃。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。