我们可以将ContextManager Decorator与__Enter __()和__EXIT __()方法混合使用,而__()方法与语句中的另一个类中的其他类中的方法相混合?
在python3.8中,我非常熟悉传统__输入__
和__退出__
魔术方法,但@coce>@contextlib.contlib.contextmanager
decorator。是否可以将单个中的两个模式与
语句混合在一起?
以下(高度人为)脚本应该更清楚地解释问题。 contextClass.enter_context_function()
和contextClass.exit_context_function()
是否有定义仅使用context_function()
函数并使单元测试通过?还是这些模式是互斥的?
import contextlib
NUMBERS = []
@contextlib.contextmanager
def context_function():
NUMBERS.append(3)
try:
yield
finally:
NUMBERS.append(5)
class ContextClass:
def __init__(self):
self.numbers = NUMBERS
self.numbers.append(1)
def __enter__(self):
self.numbers.append(2)
self.enter_context_function() # should append 3
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.exit_context_function() # should append 5
self.numbers.append(6)
def function_call(self):
self.numbers.append(4)
def enter_context_function(self):
# FIX ME!
pass
def exit_context_function(self):
# FIX ME!
pass
if __name__ == "__main__":
import unittest
class TestContextManagerFunctionAndClass(unittest.TestCase):
def test_context_function_and_class(self):
with ContextClass() as cc:
cc.function_call()
self.assertEqual(NUMBERS, [1, 2, 3, 4, 5, 6])
unittest.main()
我知道有更好的方法可以解决一个类似的问题(特别是重写context_function
作为具有其自己_____ __
和__ exit> __ exit __
方法的类,但是我M试图更好地了解上下文Manager Decorator的工作方式。
In python3.8 I'm very familiar with the traditional __enter__
and __exit__
magic methods but new to the @contextlib.contextmanager
decorator. Is it possible to mix the two patterns inside a single with
statement?
The following (highly contrived) script should explain the problem more clearly. Is there a definition of ContextClass.enter_context_function()
and ContextClass.exit_context_function()
(I imagine something needs to change inside __init__
as well) that only use the context_function()
function and makes the unit tests pass? Or are these patterns mutually exclusive?
import contextlib
NUMBERS = []
@contextlib.contextmanager
def context_function():
NUMBERS.append(3)
try:
yield
finally:
NUMBERS.append(5)
class ContextClass:
def __init__(self):
self.numbers = NUMBERS
self.numbers.append(1)
def __enter__(self):
self.numbers.append(2)
self.enter_context_function() # should append 3
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.exit_context_function() # should append 5
self.numbers.append(6)
def function_call(self):
self.numbers.append(4)
def enter_context_function(self):
# FIX ME!
pass
def exit_context_function(self):
# FIX ME!
pass
if __name__ == "__main__":
import unittest
class TestContextManagerFunctionAndClass(unittest.TestCase):
def test_context_function_and_class(self):
with ContextClass() as cc:
cc.function_call()
self.assertEqual(NUMBERS, [1, 2, 3, 4, 5, 6])
unittest.main()
I understand there are better ways to solve a similar problem (specifically rewriting context_function
as a class with its own __enter__
and __exit__
methods, but I'm trying to better understand exactly how the contextmanager decorator works.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
__ Init __
无需更改。 “使单位测试通过”的手册方式是:但是,有点缺少上下文管理者的点。它们旨在在a
另请注意,如书面,如果加剧后代码,则无法达到 line(5) line(“拆卸”)。应该像这样写:
No change in the
__init__
is necessary. The manual way which "makes the unit tests pass" would be:However, it's kind of missing the point of context-managers. They're intended to be used in a with-statement.
Also note that, as written, the
NUMBERS.append(5)
line (the "teardown") may not be reached if the code after yielding raises. It should be written like this: