Python的“ with”语句:使用__enter __ / __ exit__正确嵌套/派生类
作者:互联网
如何正确嵌套与类相关的行为(例如,在派生或实例化时)?
这对我有用,但我想知道是否有专用的方法可以做到这一点:
class class_a:
def __init__(self):
print('class_a::__init__')
def __enter__(self):
print('class_a::__enter__')
return self
def __exit__(self, type, exit, tb):
print('class_a::__exit__')
class class_b(class_a):
def __init__(self):
class_a.__init__(self)
print('class_b::__init__')
def __enter__(self):
class_a.__enter__(self)
print('class_b::__enter__')
return self
def __exit__(self, type, exit, tb):
class_a.__exit__(self, type, exit, tb)
print('class_b::__exit__', type, exit, tb)
with class_b():
print('ready')
try:
signal.pause()
except:
pass
一种不同的方法是像这样实现class_b:
class class_b:
def __init__(self):
self._class_a_inst = class_a()
print('class_b::__init__')
def __enter__(self):
self._class_a_inst.__enter__()
print('class_b::__enter__')
return self
def __exit__(self, type, exit, tb):
self._class_a_inst.__exit__(type, exit, tb)
print('class_b::__exit__', type, exit, tb)
__enter __()/ __exit __()行为有什么区别吗?
解决方法:
理想情况下,使用contextlib.contextmanager.对于派生的情况:
import contextlib
class context_mixin:
def __enter__(self):
self.__context = self.context()
return self.__context.__enter__()
def __exit__(self, *args):
return self.__context.__exit__(*args)
class class_a(context_mixin):
@contextlib.contextmanager
def context(self):
print('class_a enter')
try:
yield self
finally:
print('class_a exit')
class class_b(class_a):
@contextlib.contextmanager
def context(self):
with super().context():
print('class_b enter')
try:
yield self
finally:
print('class_b exit')
在Python 2中,super()必须是super(class_b,self).
与您的代码相比,行为有所变化:此代码在退出a之前先退出b,这意味着范围嵌套.您已经编写了代码以其他顺序执行操作,尽管更改起来很容易.通常它没有什么区别,但是当确实重要时,您通常希望将其嵌套.因此,对于一个(公认的)示例,如果class_a代表打开的文件,而class_b代表某种文件格式,则class_a的退出路径将关闭该文件,而class_b的退出路径将写入尚未缓冲的所有更改.做出承诺.显然b应该首先发生!
对于持有另一个对象的情况:
class class_b(context_mixin):
def __init__(self):
self.a = class_a()
@contextlib.contextmanager
def context(self):
with self.a:
print('class_b enter')
try:
yield self
finally:
print('class_b exit')
标签:derived-class,with-statement,python 来源: https://codeday.me/bug/20191119/2035506.html