2012-02-27 14 views
4

私はStringIOがファイルオブジェクトのように振る舞い、open('somefile.txt')から得ることをダックタイピングすることを理解しています。with文で使用できるPythonクラスを定義するにはどうすればよいですか?

今、私はwith文でStringIOを使用したい:

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__メソッドを定義するにはどうすればよいですか? withステートメントで使用できるクラスからPythonに何が期待されていますか?

答えて

8

context managerを書く必要があります。プロトコル全体を書こうとしない場合は、contextlib.contextmanagerデコレータを使用すると簡略化された方法があります。ただ、やり過ぎ発電機で使用するために 以上であるcontextlib、使用行うことになる例与える

+0

私はcontextlib.closingを使って例を書いていましたが、あなたはそれを打ち負かしました.. – DSM

+0

あなたの場合(オブジェクトを閉じたいだけです)、 'contextlibを使う方が簡単かもしれません。閉鎖する。 –

+0

@ DSM:Lol ...あなたはcontextlib.closingに関するコメントに私を打つ:D –

0

__exit__と同じように__enter__メソッドを定義します。これらは、withステートメントで使用するオブジェクトに必要な2つのメソッドです。詳細はthisを参照してください。

1

:ここ

は、コンテキストマネージャの素晴らしく、有用な例です。 私はデビッド・ビーズリーのブログでそれを見つけた:私はtimeitモジュールから使用トリックを

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

とちょうどプラットフォームごとの最高のタイマーを使用するように少しそれを変更し、 :

# 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) 

とyあなたの出力を印刷してください。 私はこの例が好きで、共有したいと思っていました。

関連する問題