मुख्य सामग्री पर जाएं
मॉड्यूल 9 · पाठ 3 का 4पाठ्यक्रम में 35/36~12 min
मॉड्यूल पाठ (3/4)

संदर्भ प्रबंधक: साथ और __enter__/__exit__

संदर्भ प्रबंधक एक ऑब्जेक्ट है जिसका उपयोग आप with के साथ करते हैं। यह इसकी गारंटी देता है कुछ सेटअप/क्लीनअप ऑपरेशन हमेशा होते रहते हैं, त्रुटियाँ होने पर भी। विहित उदाहरण: किसी फ़ाइल को खोलना और बंद करना।

with पैटर्न

Python
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।

एक समय में एक से अधिक

Python
with open("a.txt") as f, open("b.txt") as g:
    dati_a = f.read()
    dati_b = g.read()

अपना स्वयं का संदर्भ प्रबंधक (वर्ग) लिखना

आपको दो डंडर विधियों को परिभाषित करने की आवश्यकता है: __enter__ और __exit__।

Python
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 आपको एक संदर्भ प्रबंधक के रूप में लिखने की सुविधा देता है जनरेटर फ़ंक्शन:

Python
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 त्रुटियां होने पर भी सफाई की गारंटी देता है।

दबाएँ: अपवाद को अनदेखा करें

Python
from contextlib import suppress

with suppress(FileNotFoundError):
    open("forse-non-esiste.txt").read()
# se il file non c'è, nessun errore propaga

ख़तरा: with केवल उन वस्तुओं के लिए जो इसका समर्थन करते हैं

Python
x = 42
with x:  # AttributeError: __enter__
    ...

@contextmanager के साथ संदर्भ प्रबंधक लिखना

मानक लाइब्रेरी का contextlib मॉड्यूल @contextmanager नामक अत्यधिक सुविधाजनक डेकोरेटर निर्यात करता है, जो __enter__ और __exit__ विधियों को लागू करने वाली वर्बोज़ कक्षाएं लिखने के बजाय जनरेटर फ़ंक्शन का उपयोग करके संदर्भ प्रबंधक बनाता है। आप बस एक जेनरेटर फ़ंक्शन लिखें जो एकल yield का उपयोग करता है:

Python
from contextlib import contextmanager

@contextmanager
def manage_resource():
    # __enter__ code
    yield resource
    # __exit__ code

खुद कोशिश करना

व्यायाम#python.m9.l3.e1
प्रयास: 0लोड हो रहा है...

वैल्यूएरर को अनदेखा करते हुए int('non-numero') को आज़माने के लिए contextlib.suppress का उपयोग करें। ब्लॉक के बाद `ok = True` असाइन करें। 'ठीक' का मूल्यांकन करें.

संपादक लोड हो रहा है...
संकेत दिखाएँ

सप्रेस (ValueError) केवल वैल्यू एरर को निगलता है।

3 प्रयासों के बाद समाधान उपलब्ध है

व्यायाम की समीक्षा करें

व्यायाम#python.m9.l3.e2
प्रयास: 0लोड हो रहा है...

@contextmanager के साथ एक संदर्भ प्रबंधक `collect` लिखें जो एक खाली सूची उत्पन्न करता है और, बाहर निकलने पर, इसे एक टुपल में बदल देता है (इसे प्रिंट करें)। ब्लॉक के अंदर सूची में 1, 2, 3 जोड़ने के लिए इसका उपयोग करें। अंत में, `len(collection)` का मूल्यांकन करें जहां `collection` प्राप्त सूची है।

संपादक लोड हो रहा है...
संकेत दिखाएँ

with ब्लॉक के अंदर सूची को उजागर करने के लिए आइटम प्राप्त करें।

3 प्रयासों के बाद समाधान उपलब्ध है

अतिरिक्त चुनौती

व्यायाम#python.m9.l3.e3
प्रयास: 0लोड हो रहा है...

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 प्रयासों के बाद समाधान उपलब्ध है