Polecam użycie withinstrukcji Pythona do zarządzania zasobami, które wymagają oczyszczenia. Problem z używaniem wyraźnego close()stwierdzenia polega na tym, że musisz się martwić, że ludzie w ogóle zapomną go nazwać lub zapomną umieścić go wfinally bloku, aby zapobiec wyciekom zasobów w przypadku wystąpienia wyjątku.
Aby użyć withinstrukcji, utwórz klasę przy użyciu następujących metod:
def __enter__(self)
def __exit__(self, exc_type, exc_value, traceback)
W powyższym przykładzie użyłbyś
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)
Następnie, gdy ktoś chciałby skorzystać z twojej klasy, zrobiłby to:
with Package() as package_obj:
# use package_obj
Zmienna package_obj będzie instancją typu Package (jest to wartość zwracana przez __enter__metodę). Jego__exit__ metoda zostanie automatycznie wywołana, niezależnie od tego, czy wystąpi wyjątek.
Możesz nawet pójść o krok dalej. W powyższym przykładzie ktoś nadal może utworzyć instancję pakietu przy użyciu swojego konstruktora bez użycia withklauzuli. Nie chcesz, żeby tak się stało. Możesz to naprawić, tworząc klasę PackageResource, która definiuje metody __enter__i __exit__. Następnie klasa Package zostanie zdefiniowana ściśle wewnątrz __enter__metody i zwrócona. W ten sposób osoba dzwoniąca nigdy nie może utworzyć instancji klasy Package bez użycia withinstrukcji:
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()
Użyłbyś tego w następujący sposób:
with PackageResource() as package_obj:
# use package_obj