如何定义可以与with语句一起使用的Python类?

时间:2012-02-27 03:35:50

标签: python

我理解StringIO就像一个文件对象,可以从open('somefile.txt')中获取内容。

现在我想将StringIOwith声明一起使用:

with StringIO('some string') as fh: # fh as in "file handle"
    data = [stuff from stuff in fh.read()]

但是Python抱怨类型StringIO没有__exit__方法。在继承StringIO之后:

class MyStringIO(StringIO):
    def __exit__(self):
        self.close()

我现在得到一个关于没有__enter__方法的例外。如何定义__enter__方法? Python对可以与with语句一起使用的类有什么期望?

3 个答案:

答案 0 :(得分:8)

你需要写一个context manager。如果您不想编写整个协议,可以使用contextlib.contextmanager装饰器简化它。

答案 1 :(得分:1)

只是举一个例子,它可能会过度使用contextlib,更多 用于发电机:

这是一个很好用的上下文管理器示例。 我在David Beazley的博客中找到了它:

http://dabeaz.blogspot.de/2010/02/context-manager-for-timing-benchmarks.html

并且稍微修改了它以使用每个平台的最佳计时器, 我在timeit模块中使用的一个技巧:

# benchmark.py
import timeit
class benchmark(object):
    from timeit import default_timer as timer
    def __init__(self, name):
        self.name = name
    def __enter__(self):
        self.start = self.timer()
    def __exit__(self, ty, val, tb):
        end = self.timer()
        print("%s : %0.3f seconds" % (self.name, end-self.start))
        return False

现在,它为您提供了一个可以像这样使用的上下文管理器:

with benchmark('algorithm 1'):
    ... (some computation)
with benchmark('other approach'):
    ... (some other computation)

然后打印输出。 我喜欢这个例子,想分享它。

答案 2 :(得分:0)

您定义__enter__方法,就像使用__exit__一样。这些是对象与with语句一起使用所需的两种方法,有关详细信息,请参阅this