Python上下文管理的成员变量?

时间:2014-11-22 00:33:13

标签: python

上下文管理器定义设置/清除功能__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.

2 个答案:

答案 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