मॉड्यूल पाठ (3/4)
संदर्भ प्रबंधक: साथ और __enter__/__exit__
संदर्भ प्रबंधक एक ऑब्जेक्ट है जिसका उपयोग आप with के साथ करते हैं। यह इसकी गारंटी देता है
कुछ सेटअप/क्लीनअप ऑपरेशन हमेशा होते रहते हैं, त्रुटियाँ होने पर भी।
विहित उदाहरण: किसी फ़ाइल को खोलना और बंद करना।
with पैटर्न
with open("note.txt", "w") as f:
f.write("ciao")
# qui f è già chiuso, anche se write() ha sollevato un'eccezioneस्पष्ट अंग्रेजी में: "साथ संसाधन X को f के रूप में खोलें, ऐसा करें। जब हो जाए
(कुछ भी हो), एक्स बंद करें।" with के बिना आपको लिखना पड़ेगा
हर बार एक try/finally।
एक समय में एक से अधिक
with open("a.txt") as f, open("b.txt") as g:
dati_a = f.read()
dati_b = g.read()अपना स्वयं का संदर्भ प्रबंधक (वर्ग) लिखना
आपको दो डंडर विधियों को परिभाषित करने की आवश्यकता है: __enter__ और __exit__।
class Timer:
def __enter__(self):
import time
self.t0 = time.perf_counter()
return self # è l'oggetto che finisce dopo "as"
def __exit__(self, exc_type, exc_value, traceback):
import time
self.elapsed = time.perf_counter() - self.t0
# ritornare True ingoia l'eccezione; di solito non lo vuoi
return False
with Timer() as t:
sum(range(10**6))
t.elapsed # quanto è durato- ब्लॉक में प्रवेश करने पर
__enter__(self)को कॉल किया जाता है; लौटाया गया मान वही है जो आपकोasके बाद मिलता है। __exit__(self, exc_type, exc_value, tb)को बाहर निकलने पर (हमेशा) बुलाया जाता है। यदि यहTrueलौटाता है, तो कोई भी अपवाद दबाया जाता है।
शॉर्टकट: @contextmanager
contextlib.contextmanager आपको एक संदर्भ प्रबंधक के रूप में लिखने की सुविधा देता है
जनरेटर फ़ंक्शन:
from contextlib import contextmanager
@contextmanager
def timer():
import time
t0 = time.perf_counter()
try:
yield # qui sta il blocco "with"
finally:
elapsed = time.perf_counter() - t0
print(f"durata: {elapsed:.4f}s")
with timer():
sum(range(10**6))पहले yield का कोड __enter__ है, बाद का कोड __exit__ है।
try/finally त्रुटियां होने पर भी सफाई की गारंटी देता है।
दबाएँ: अपवाद को अनदेखा करें
from contextlib import suppress
with suppress(FileNotFoundError):
open("forse-non-esiste.txt").read()
# se il file non c'è, nessun errore propagaख़तरा: with केवल उन वस्तुओं के लिए जो इसका समर्थन करते हैं
x = 42
with x: # AttributeError: __enter__
...@contextmanager के साथ संदर्भ प्रबंधक लिखना
मानक लाइब्रेरी का contextlib मॉड्यूल @contextmanager नामक अत्यधिक सुविधाजनक डेकोरेटर निर्यात करता है, जो __enter__ और __exit__ विधियों को लागू करने वाली वर्बोज़ कक्षाएं लिखने के बजाय जनरेटर फ़ंक्शन का उपयोग करके संदर्भ प्रबंधक बनाता है। आप बस एक जेनरेटर फ़ंक्शन लिखें जो एकल yield का उपयोग करता है:
from contextlib import contextmanager
@contextmanager
def manage_resource():
# __enter__ code
yield resource
# __exit__ codeखुद कोशिश करना
वैल्यूएरर को अनदेखा करते हुए int('non-numero') को आज़माने के लिए contextlib.suppress का उपयोग करें। ब्लॉक के बाद `ok = True` असाइन करें। 'ठीक' का मूल्यांकन करें.
संकेत दिखाएँ
सप्रेस (ValueError) केवल वैल्यू एरर को निगलता है।
3 प्रयासों के बाद समाधान उपलब्ध है
व्यायाम की समीक्षा करें
@contextmanager के साथ एक संदर्भ प्रबंधक `collect` लिखें जो एक खाली सूची उत्पन्न करता है और, बाहर निकलने पर, इसे एक टुपल में बदल देता है (इसे प्रिंट करें)। ब्लॉक के अंदर सूची में 1, 2, 3 जोड़ने के लिए इसका उपयोग करें। अंत में, `len(collection)` का मूल्यांकन करें जहां `collection` प्राप्त सूची है।
संकेत दिखाएँ
with ब्लॉक के अंदर सूची को उजागर करने के लिए आइटम प्राप्त करें।
3 प्रयासों के बाद समाधान उपलब्ध है
अतिरिक्त चुनौती
Write a custom context manager using the `@contextmanager` decorator from `contextlib`. The context manager must be named `mock_session`. Upon entry, it must append `'start'` to a global list `log_list = []`, yield control using `yield`, and upon exit append `'stop'`. Finally, evaluate `log_list` after using the context manager with `with mock_session():`.
संकेत दिखाएँ
'स्टॉप' जोड़ने से पहले निष्पादन को निलंबित करने के लिए मॉक_सेशन के अंदर उपज का उपयोग करें।
3 प्रयासों के बाद समाधान उपलब्ध है