মূল কন্টেন্টে যান
মডিউল 9 · 3-এর পাঠ 4কোর্সে 35/36~12 min
মডিউল পাঠ (3/4)

প্রসঙ্গ ম্যানেজার: __এন্টার__/__প্রস্থান__ সহ

একটি প্রসঙ্গ পরিচালক হল একটি বস্তু যা আপনি 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 ত্রুটি ঘটলেও পরিষ্কার করার নিশ্চয়তা দেয়৷

suppress: একটি ব্যতিক্রম উপেক্ষা করুন

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 মডিউলটি __enter__ এবং __enter__ এবং __enter__ এবং __enter__ পদ্ধতি প্রয়োগ করে ভারবোস ক্লাস লেখার পরিবর্তে জেনারেটর ফাংশন ব্যবহার করে প্রসঙ্গ পরিচালক তৈরি করতে @contextmanager নামে একটি অত্যন্ত সুবিধাজনক ডেকোরেটর রপ্তানি করে। আপনি শুধু একটি জেনারেটর ফাংশন লিখুন যা একটি একক yield ব্যবহার করে:

Python
from contextlib import contextmanager

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

নিজে চেষ্টা করে দেখুন

ব্যায়াম#python.m9.l3.e1
প্রচেষ্টা: 0লোড হচ্ছে...

ValueError উপেক্ষা করে int('non-numero') চেষ্টা করতে contextlib.suppress ব্যবহার করুন। ব্লক অ্যাসাইন করার পর `ok = True`। 'ঠিক আছে' মূল্যায়ন করুন।

সম্পাদক লোড হচ্ছে...
ইঙ্গিত দেখান

suppress(ValueError) শুধুমাত্র ValueErrorকে গ্রাস করে।

সমাধান 3 প্রচেষ্টার পরে উপলব্ধ

ব্যায়াম পর্যালোচনা করুন

ব্যায়াম#python.m9.l3.e2
প্রচেষ্টা: 0লোড হচ্ছে...

@contextmanager এর সাথে একটি প্রসঙ্গ ম্যানেজার `collect` লিখুন যা একটি খালি তালিকা দেয় এবং প্রস্থান করার সময় এটিকে একটি টিপলে রূপান্তর করে (এটি প্রিন্ট করুন)। ব্লকের ভিতরে তালিকায় 1, 2, 3 যুক্ত করতে এটি ব্যবহার করুন। শেষে, `লেন(সংগ্রহ)` মূল্যায়ন করুন যেখানে `সংগ্রহ` ফলিত তালিকা।

সম্পাদক লোড হচ্ছে...
ইঙ্গিত দেখান

ব্লকের ভিতরে তালিকা প্রকাশ করতে আইটেম ফলন।

সমাধান 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():`.

সম্পাদক লোড হচ্ছে...
ইঙ্গিত দেখান

'স্টপ' যুক্ত করার আগে এক্সিকিউশন স্থগিত করতে mock_session-এর ভিতরে ফলন ব্যবহার করুন।

সমাধান 3 প্রচেষ্টার পরে উপলব্ধ