首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python上下文管理成员变量?

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

Stack Overflow用户
提问于 2014-11-22 08:33:13
回答 2查看 1.8K关注 0票数 10

上下文管理器定义了设置/清理功能__enter____exit__。太棒了。我想保留一个作为成员变量。当我的类对象超出作用域时,我希望执行此清理。这基本上就是我所理解的C++构造函数/析构函数自动发生的行为。

代码语言:javascript
复制
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.
EN

回答 2

Stack Overflow用户

发布于 2014-11-22 08:40:09

Python不做C++风格的RAII (“资源获取就是初始化”,意思是你在构造函数中获取的任何东西,你在析构函数中释放)。事实上,除了C++之外,几乎没有其他语言可以实现C++风格的RAII。Python的上下文管理器和with语句是一种不同的方法,可以实现C++对RAII所做的事情,以及大多数其他语言对finally语句、guard语句等所做的事情(当然,Python也有finally )。

你所说的“当我的类对象超出范围时”到底是什么意思?

对象不会超出作用域;引用(或变量,或名称,随您喜欢)会超出作用域。在最后一个引用超出作用域之后的一段时间(对于CPython,这是立即进行的,除非它涉及到引用周期;对于其他实现,通常不会),该对象将被垃圾收集。

如果你想在你的对象被垃圾收集时做一些清理,你可以使用__del__方法。但这很少是你真正想要的。(实际上,有些类有一个__del__方法,只是用来警告用户他们忘记清理了,而不是静默地清理。)

更好的解决方案是使Animal本身成为上下文管理器,这样它就可以管理其他上下文管理器--或者只是显式地管理事物。然后你可以写:

代码语言:javascript
复制
if True:
    with Animal() as animal:
        # do stuff
    # now the file is closed

下面是一个例子:

代码语言:javascript
复制
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即可。

票数 5
EN

Stack Overflow用户

发布于 2014-11-22 08:40:19

如果有意义,我会给类一个close函数,然后使用closing上下文管理器:

代码语言:javascript
复制
class MyClass(object):
    def __init__(self):
        self.resource = acquire_resource()

    def close():
        release_resource(self.resource)

然后像这样使用它:

代码语言:javascript
复制
from contextlib import closing

with closing(MyClass()) as my_object:
    # use my_object
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27072664

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档