Python: Python の with と C# の using の違い
先日、友人から「Python の with って C# でいうとこの using なのかな!?」ってメッセージがきました。
気になったので試したところ、結果は using と同義ではないことがわかりました。
↑ は誤りです。ただしくは破棄を保証するものではなく下記の通りとなります。
(yuba さんご指摘ありがとうございました!)
そもそも C# の using は、オブジェクトを破棄する処理を呼び出すことを保証するものです。
他の用途としては当該オブジェクトのスコープ範囲を括ることも挙げられます。
したがって using を抜けるともう既にそのオブジェクトはスコープの範囲外となり、参照することはできません。
下記が using のサンプルです。
public void Anything() {
    using (FileStream fs = new FileStream("hoge.txt", FileMode.Read)) {
        // anything
    }
    // fs はもう破棄されている
}
using ステートメントを抜けるタイミングで Dispose が呼ばれます。
さらにスコープの範囲は using 内に留まります。
次に Python の with です。
Python 2.7 を主に使っているので 2 系のドキュメントから with の説明をかいつまんで拝借すると…
with 文は、 enter() メソッドがエラーなく終了した場合には exit() が常に呼ばれることを保証します。ですので、もしエラーがターゲットリストへの代入中にエラーが発生した場合には、これはそのスイートの中で発生したエラーと同じように扱われます。
引用: http://docs.python.jp/2/reference/compound_stmts.html#with
つまりは __enter__() メソッドがエラーなく終了した場合には __exit__() が常に呼ばれることを保証 するものなので using とは意味が違います。
具体的に下記に with のサンプルコードを示します。
// with-test.py
class WithTest:
    def __init__(self, hoge):
        print('__init__')
        self.hoge = hoge
    
    def printer(self):
        print(self.hoge)
    
    def __enter__(self):
        print('__enter__')
        return self
    
    def __exit__(self, type, value, traceback):
        print('__exit__')
    
    
with WithTest('test') as t:
    t.printer()
t.printer()
実行結果は以下の通り。
$ python with-test.py
__init__
__enter__
test
__exit__
test
何が保証されるか、そこに違いがありましたというお話でした。