了解python3嵌套上下文管理器

时间:2019-03-15 09:12:00

标签: python-3.x nested contextmanager

我有一堂课

class OuterCtxManager:
  def __enter__(self): 
    print('Outer enter')
  def __exit__(self, exc_type, exc_val, exc_tb):
    print('Outer exit')

当我这样做时:

def test_func():
  return OuterCtxManager()

with test_func() as context_manager:
  print('context_manager')

它打印:

Outer enter
context_manager
Outer exit

为什么尽管在函数中已创建的对象上使用了上下文管理器,但为什么仍然打印Outer enterOuter exit? (而不是在创建with OuterCtxManager() as ocm之类的对象时直接使用)

接下来是有趣的事情:

当我这样做时:

def test_func():
  first_object = OuterCtxManager()
  second_object = OuterCtxManager()
  return [first_object, second_object]

with test_func() as context_manager:
  print('context_manager')

它引发:

  

AttributeError:输入

最后,当我这样做时:

class OuterCtxManager:
  def __init__(self):
    self.inner_ctx = InnerCtxManager()
  def __enter__(self): 
    print('Outer enter')
  def __exit__(self, exc_type, exc_val, exc_tb):
    print('Outer exit')

class InnerCtxManager:
  def __init__(self):
    print('inner_created')
  def __enter__(self): 
    print('Inner enter')
  def __exit__(self, exc_type, exc_val, exc_tb):
    print('Inner exit')


def test_func():
  first_object = OuterCtxManager()
  return first_object

with test_func() as context_manager:
  print('context_manager')

它打印:

inner_created
Outer enter
context_manager
Outer exit

我没有任何错误。我都没有得到Inner createdInner enter。为什么呢?

Sandbox

1 个答案:

答案 0 :(得分:0)

  

尽管在函数中已创建的对象上使用了上下文管理器,为什么仍然打印出外部进入和外部退出?

您定义的with语句表示python应该在执行__enter__语句的内容之前调用with,然后执行__exit__

对象是否已全部初始化都没关系。无论如何,with语句将调用__enter____exit__

  

它引发AttributeError: enter

当您返回一个元组并且该元组不包含__enter__的定义时,将引发此错误。

  

我没有任何错误。我都没有创建内部,也没有内部输入。为什么呢?

您没有得到任何错误,因为您正确地将withOuterCtxManager一起使用了Inner enter语句,并且因为没有使用Inner exitwith而没有得到输出不要使用InnerCtxManager类型的compareTo语句。