class Package:
def __init__(self):
self.files = []
# ...
def __del__(self):
for file in self.files:
os.unlink(file)
__del__(self)
上記はAttributeError例外で失敗します。Pythonは保証しないが呼び出されたときに「グローバル変数」(このコンテキストではメンバー データ?) が存在する__del__()
かどうかを確認します。これが例外の原因である場合、オブジェクトが適切に破棄されることをどのように確認すればよいでしょうか。
ベストアンサー1
with
クリーンアップする必要があるリソースを管理するには、Python のステートメントを使用することをお勧めします。明示的なclose()
ステートメントを使用する場合の問題は、例外が発生したときにリソース リークを防ぐために、ユーザーがステートメントを呼び出すことを忘れたり、ブロックに配置することを忘れたりするのではないfinally
かと心配する必要があることです。
ステートメントを使用するにはwith
、次のメソッドを持つクラスを作成します。
def __enter__(self)
def __exit__(self, exc_type, exc_value, traceback)
上記の例では、
class Package:
def __init__(self):
self.files = []
def __enter__(self):
return self
# ...
def __exit__(self, exc_type, exc_value, traceback):
for file in self.files:
os.unlink(file)
その後、誰かがあなたのクラスを使いたいときは、次のようにします。
with Package() as package_obj:
# use package_obj
変数 package_obj は Package 型のインスタンスになります (メソッドによって返される値です__enter__
)。__exit__
例外が発生したかどうかに関係なく、そのメソッドが自動的に呼び出されます。
このアプローチをさらに一歩進めることもできます。上記の例では、 句を使用せずにコンストラクターを使用して Package をインスタンス化できますwith
。これは避けたいものです。__enter__
および__exit__
メソッドを定義する PackageResource クラスを作成することで、この問題を修正できます。すると、 Package クラスは メソッド内で厳密に定義され__enter__
、返されます。こうすることで、呼び出し元はステートメントを使用せずに Package クラスをインスタンス化できなくなりますwith
。
class PackageResource:
def __enter__(self):
class Package:
...
self.package_obj = Package()
return self.package_obj
def __exit__(self, exc_type, exc_value, traceback):
self.package_obj.cleanup()
これを次のように使用します。
with PackageResource() as package_obj:
# use package_obj