v Pythonu, s prohlášením se používá při zpracování výjimek, aby byl kód čistší a mnohem čitelnější. Zjednodušuje správu běžných zdrojů, jako jsou datové proudy souborů. Podívejte se na následující příklad kódu, jak použití příkazu with dělá kód čistším.
Python3
fmoviez
# file handling> # 1) without using with statement> file> => open>(>'file_path'>,>'w'>)> file>.write(>'hello world !'>)> file>.close()> # 2) without using with statement> file> => open>(>'file_path'>,>'w'>)> try>:> >file>.write(>'hello world'>)> finally>:> >file>.close()> |
>
>
Python3
# using with statement> with>open>(>'file_path'>,>'w'>) as>file>:> >file>.write(>'hello world !'>)> |
>
>
příkaz sed
Všimněte si, že na rozdíl od prvních dvou implementací není potřeba volat file.close() při použití s příkazem. Samotný příkaz with zajišťuje řádné získání a uvolnění zdrojů. Výjimka během volání file.write() v první implementaci může zabránit správnému uzavření souboru, což může způsobit několik chyb v kódu, tj. mnoho změn v souborech se neprojeví, dokud není soubor správně uzavřen. Druhý přístup ve výše uvedeném příkladu se stará o všechny výjimky, ale pomocí příkazu with je kód kompaktní a mnohem čitelnější. Prohlášení tedy pomáhá vyhnout se chybám a únikům tím, že zajistí, aby byl prostředek správně uvolněn, když je kód využívající prostředek zcela spuštěn. Příkaz with se běžně používá se souborovými proudy, jak je uvedeno výše, a se zámky, sokety, podprocesy a telnety atd.
Podpora příkazu with v uživatelsky definovaných objektech
V open() není nic zvláštního, díky čemuž je použitelný s příkazem with a stejnou funkčnost lze poskytnout v uživatelsky definovaných objektech. Podpora pomocí příkazu ve vašich objektech zajistí, že nikdy nenecháte žádný zdroj otevřený. Pro použití s příkazem v uživatelsky definovaných objektech stačí přidat metody __enter__() a __exit__() do objektových metod. Pro další objasnění zvažte následující příklad.
Python3
# a simple file writer object> class> MessageWriter(>object>):> >def> __init__(>self>, file_name):> >self>.file_name>=> file_name> > >def> __enter__(>self>):> >self>.>file> => open>(>self>.file_name,>'w'>)> >return> self>.>file> >def> __exit__(>self>,>*>args):> >self>.>file>.close()> # using with statement with MessageWriter> with MessageWriter(>'my_file.txt'>) as xfile:> >xfile.write(>'hello world'>)> |
>
>
Podívejme se na výše uvedený kód. Pokud si všimnete, co následuje za klíčovým slovem with, je konstruktor MessageWriter. Jakmile spuštění vstoupí do kontextu příkazu with, vytvoří se objekt MessageWriter a python pak zavolá metodu __enter__() . V této metodě __enter__() inicializujte prostředek, který chcete v objektu použít. Tato metoda __enter__() by měla vždy vracet deskriptor získaného zdroje. Co jsou deskriptory zdrojů? Toto jsou úchyty poskytované operačním systémem pro přístup k požadovaným prostředkům. V následujícím bloku kódu je soubor deskriptorem zdroje souborového proudu.
Krajta
mvc pro java
file> => open>(>'hello.txt'>)> |
>
>
Ve výše uvedeném příkladu MessageWriter metoda __enter__() vytvoří deskriptor souboru a vrátí jej. Název xfile se zde používá jako odkaz na deskriptor souboru vrácený metodou __enter__(). Blok kódu, který používá získaný prostředek, je umístěn uvnitř bloku příkazu with. Jakmile se provede kód uvnitř bloku with, zavolá se metoda __exit__() . Všechny získané prostředky jsou uvolněny metodou __exit__() . Takto používáme příkaz with s uživatelem definovanými objekty. Toto rozhraní metod __enter__() a __exit__(), které poskytuje podporu příkazu with v uživatelsky definovaných objektech, se nazývá Správce kontextu .
Modul contextlib
Správce kontextu založený na třídách, jak je uvedeno výše, není jediným způsobem, jak podporovat příkaz with v uživatelsky definovaných objektech. The contextlib modul poskytuje několik dalších abstrakcí postavených na základním rozhraní správce kontextu. Zde je návod, jak můžeme přepsat správce kontextu pro objekt MessageWriter pomocí modulu contextlib.
stáhněte si youtube pomocí vlc
Python3
from> contextlib>import> contextmanager> class> MessageWriter(>object>):> >def> __init__(>self>, filename):> >self>.file_name>=> filename> >@contextmanager> >def> open_file(>self>):> >try>:> >file> => open>(>self>.file_name,>'w'>)> >yield> file> >finally>:> >file>.close()> # usage> message_writer>=> MessageWriter(>'hello.txt'>)> with message_writer.open_file() as my_file:> >my_file.write(>'hello world'>)> |
>
>
V tomto příkladu kódu kvůli výtěžek ve své definici je funkce open_file() a funkce generátoru . Když je volána tato funkce open_file(), vytvoří deskriptor prostředku s názvem soubor. Tento deskriptor prostředku je poté předán volajícímu a je zde reprezentován proměnnou my_file. Po provedení kódu uvnitř bloku with se řízení programu vrátí zpět k funkci open_file(). Funkce open_file() obnoví své provádění a spustí kód následující po příkazu yield. Tato část kódu, která se objeví po výpisu výnosu, uvolní získané zdroje. Zde je @contextmanager a dekoratér . Předchozí implementace založená na třídách a tato implementace kontextových manažerů založená na generátoru jsou interně stejné. Zatímco pozdější se zdá čitelnější, vyžaduje znalost generátorů, dekoratérů a výnosu.