上下文管理器定义设置/清除功能__enter__
和__exit__
。真棒。我想保留一个作为成员变量。当我的类对象超出范围时,我希望执行此清理。这基本上是我理解的行为,使用C ++构造函数/析构函数自动发生。
class Animal(object):
def __init__(self):
self.datafile = open("file.txt") # This has a cleanup function
# I wish I could say something like...
with open("file.txt") as self.datafile: # uh...
def makeSound(self):
sound = self.datafile # I'll be using it later
# Usage...
if True:
animal = Animal()
# file should be cleaned up and closed at this point.
答案 0 :(得分:2)
如果有意义,我会给类close
函数,然后使用closing
上下文管理器:
class MyClass(object):
def __init__(self):
self.resource = acquire_resource()
def close():
release_resource(self.resource)
然后使用它:
from contextlib import closing
with closing(MyClass()) as my_object:
# use my_object
答案 1 :(得分:1)
Python不做C ++风格的RAII("资源获取是初始化",意思是你在构造函数中获得的任何东西,你在析构函数中释放)。事实上,除了C ++之外,几乎 no 语言都是C ++风格的RAII。 Python的上下文管理器和with
语句是一种不同的方式,可以实现C ++与RAII相同的功能,而且大多数其他语言都使用finally
语句, guard
语句等(当然,Python也有finally
。)
你到底是什么意思"当我的课堂对象超出范围"?
物品不会超出范围;引用(或变量或名称,无论你喜欢什么)。在最后一次引用超出范围之后的一段时间(对于CPython,这是立即的,除非它涉及参考周期;对于其他实现,它通常不是),该对象将被垃圾收集
如果要在对象进行垃圾回收时进行一些清理,可以使用__del__
方法。但这很少是你真正想要的。 (事实上,有些类只有一个__del__
方法,只是为了警告用户他们忘了清理,而不是默默地清理。)
更好的解决方案是让Animal
本身成为一个上下文管理器,这样它就可以管理其他上下文管理器 - 或者只是明确地管理事物。然后你可以写:
if True:
with Animal() as animal:
# do stuff
# now the file is closed
以下是一个例子:
class Animal(object):
def __init__(self):
self.datafile = open("file.txt")
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.datafile.close()
def makeSound(self):
sound = self.datafile # I'll be using it later
(刚刚从__exit__
结尾那样意味着,在调用self.datafile.close()
之后,如果没有异常,我们会成功地做任何事情,或者如果有异常则重新提出相同的异常。所以,你不必写任何明确的东西来实现这一点。)
但通常情况下,如果您要将类创建到上下文管理器中,您还需要添加一个明确的close
。就像文件一样。一旦你这样做,你真的不需要将Animal
变成一个上下文管理器;你可以使用closing
。