از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
مدیران زمینه پایتون
سرفصلهای مطلب
معرفی
یکی از مبهم ترین ویژگی های پایتون که تقریباً همه برنامه نویسان پایتون، حتی مبتدیان، از آن استفاده می کنند، اما واقعا نمی دانند، این است. مدیران زمینه. شما احتمالا آنها را در قالب دیده اید with عباراتی که معمولاً برای اولین بار در هنگام یادگیری باز کردن فایل ها در پایتون با آنها مواجه می شوند. اگرچه مدیران زمینه در ابتدا کمی عجیب به نظر می رسند، اما وقتی واقعاً در آنها غوطه ور می شویم، انگیزه و تکنیک های پشت آن را درک می کنیم، به یک سلاح جدید در زرادخانه برنامه نویسی خود دسترسی پیدا می کنیم. بنابراین بدون هیچ مقدمه ای، بیایید به آن شیرجه بزنیم!
انگیزه: مدیریت منابع
“نیاز مادر اختراع است”
برای اینکه واقعاً بفهمیم مدیر زمینه چیست و چگونه میتوانیم از آن استفاده کنیم، ابتدا باید انگیزههای پشت آن را بررسی کنیم – ضرورتهایی که باعث ایجاد این “اختراع” شد.
انگیزه اصلی مدیران زمینه مدیریت منابع است. وقتی برنامه ای می خواهد به یک منبع دسترسی پیدا کند روی کامپیوتر، آن را از سیستم عامل درخواست می کند، و سیستم عامل نیز به نوبه خود، دسته ای برای آن منبع در اختیار آن قرار می دهد. برخی از نمونه های رایج این گونه منابع فایل ها و پورت های شبکه هستند. آنچه مهم است درک این است که این منابع در دسترس محدود هستند، به عنوان مثال، یک پورت شبکه می تواند توسط یک واحد استفاده شود. process در یک زمان، و تعداد محدودی پورت در دسترس است. بنابراین هر زمان که ما باز کن یک منبع، ما باید به یاد داشته باشیم بستن آن را، به طوری که منبع آزاد شود. اما متأسفانه گفتن آن آسان تر از انجام آن است.
ساده ترین راه برای انجام مدیریت منابع مناسب فراخوانی است close عملکرد پس از اتمام کار با منبع:
opened_file = open('readme.txt')
text = opened_file.read()
...
opened_file.close()
در اینجا ما در حال باز کردن فایلی به نام هستیم readme.txt، خواندن فایل و ذخیره محتوای آن در یک رشته textو پس از اتمام کار، فایل را با فراخوانی ببندید close() روش از opened_file هدف – شی. اکنون در نگاه اول ممکن است به نظر خوب برسد، اما در واقع، اصلا قوی نیست. اگر هر چیزی بین باز کردن فایل و بستن فایل اتفاقی غیرمنتظره رخ میدهد که باعث میشود برنامه در اجرای خط حاوی close بیانیه، نشت منبع وجود خواهد داشت. اینها حوادث غیر منتظره چیزی هستند که ما به آن می گوییم exceptionsیک مورد معمول زمانی است که شخصی برنامه را در حین اجرا به زور می بندد.
در حال حاضر، راه مناسب برای رسیدگی به این خواهد بود استفاده از رسیدگی به استثنا، استفاده کردن try...else بلوک ها:
try:
opened_file = open('readme.txt')
text = opened_file.read()
else:
opened_file.close()
پایتون همیشه از کد موجود در else بلوک بدون توجه به هر اتفاقی که ممکن است رخ دهد اجرا می شود. این روشی است که برنامه نویسان زبان های دیگر مدیریت منابع را مدیریت می کنند، اما برنامه نویسان پایتون مکانیسم خاصی را دریافت می کنند که به آنها امکان می دهد همان عملکرد را بدون نیاز به تمام دیگ بخار اجرا کنند. اینجاست که مدیران زمینه وارد بازی می شوند!
پیاده سازی مدیران زمینه
اکنون که ما با مهمترین بخش در مورد درک مدیران زمینه تمام شده ایم، می توانیم به اجرای آنها بپریم. برای این آموزش یک سفارشی پیاده سازی می کنیم File کلاس این کاملاً زائد است زیرا پایتون قبلاً این را ارائه کرده است، اما با این وجود، تمرین یادگیری خوبی خواهد بود زیرا ما همیشه میتوانیم با آن ارتباط برقرار کنیم. File کلاسی که قبلاً در کتابخانه استاندارد وجود دارد.
روش استاندارد و «سطح پایین» برای پیادهسازی مدیر زمینه، تعریف دو روش «جادویی» در کلاسی است که میخواهید مدیریت منابع را برای آن پیادهسازی کنید. __enter__و __exit__. اگر در حال گمراه شدن هستید، “این روش جادویی چیست؟ من قبلاً چنین چیزی نشنیده ام” – خوب، اگر برنامه نویسی شی گرا را در پایتون شروع کرده اید، مطمئناً قبلاً با یک روش جادویی روبرو شده اید. روش __init__.
به دلیل نبود کلمات بهتر، آنها روش های خاصی هستند که می توانید برای هوشمندتر کردن کلاس های خود تعریف کنید یا “جادو” را به آنها اضافه کنید. شما می توانید یک لیست مرجع خوب از تمام روش های جادویی موجود در پایتون پیدا کنید اینجا.
به هر حال، برای بازگشت به موضوع، قبل از شروع اجرای این دو روش جادویی، باید هدف آنها را درک کنیم. __enter__ روشی است که هنگام باز کردن منبع، یا به بیان کمی فنی تر، فراخوانی می شود – زمانی که ما “ورود” می کنیم زمینه زمان اجرا. این with عبارت مقدار برگشتی این روش را به هدف مشخص شده در as بند بیانیه:
class FileManager:
def __init__(self, filename):
self.filename = filename
def __enter__(self):
self.opened_file = open(self.filename)
return self.opened_file
همانطور که می بینید، __enter__ روش باز کردن منبع – فایل و برگرداندن آن است. وقتی از این استفاده می کنیم FileManager در یک with عبارت، این متد فراخوانی می شود و مقدار بازگشتی آن به متغیر هدفی که در آن ذکر کردید متصل می شود as عبارت:
with FileManager('readme.txt') as file:
text = file.read()
بیایید قسمت به قسمت آن را تجزیه کنیم. اولا، یک نمونه از FileManager کلاس زمانی ایجاد می شود که ما آن را نمونه سازی می کنیم و نام فایل را ارسال می کنیم "readme.txt" به سازنده سپس with بیانیه شروع به کار می کند روی آن را صدا می کند __enter__ روش آن FileManager شی و مقدار برگشتی را به file متغیر ذکر شده در as عبارت. سپس، در داخل with بلاک، ما می توانیم هر کاری که می خواهیم با منبع باز شده انجام دهیم.
بخش مهم دیگر پازل این است __exit__ روش. این __exit__ متد حاوی کد پاکسازی است که باید پس از اتمام کار با منبع اجرا شود. دستورالعمل های این روش مشابه دستورالعمل های موجود در این روش خواهد بود else بلوکی که قبلاً در مورد رسیدگی به استثناء بحث کردیم. برای تکرار، __exit__ روش شامل دستورالعمل هایی برای بستن صحیح کنترل کننده منبع است، به طوری که منبع برای استفاده بیشتر توسط برنامه های دیگر در سیستم عامل آزاد می شود.
حالا بیایید نگاهی به روش نوشتن این روش بیندازیم:
class FileManager:
def __exit__(self. *exc):
self.opened_file.close()
هر زمان که از نمونه های این کلاس در a استفاده شود with بیانیه، این __exit__ قبل از خروج برنامه از متد فراخوانی می شود with مسدود کردن، یا قبل از توقف برنامه به دلیل برخی استثناها. حالا بیایید به کل نگاه کنیم FileManager کلاس تا ما یک ایده کامل داشته باشیم:
class FileManager:
def __init__(self, filename):
self.filename = filename
def __enter__(self):
self.opened_file = open(self.filename)
return self.opened_file
def __exit__(self, *exc):
self.opened_file.close()
به اندازه کافی ساده، درست است؟ ما فقط عملیات باز کردن و پاکسازی را در متدهای جادویی مربوطه تعریف کردیم، و پایتون مدیریت منابع را در هر کجا که ممکن است از این کلاس استفاده شود، انجام خواهد داد. این ما را به موضوع بعدی میرساند، روشهای مختلفی که میتوانیم از کلاسهای مدیریت متن استفاده کنیم، مانند این FileManager کلاس
استفاده از Context Managers
در اینجا چیز زیادی برای توضیح وجود ندارد، بنابراین به جای نوشتن پاراگراف های طولانی، اجازه دهید نگاهی به چند قطعه کد در این بخش بیندازیم:
file = FileManager('readme.txt')
with file as managed_file:
text = managed_file.read()
print(text)
with FileManager('readme.txt') as managed_file:
text = managed_file.read()
print(text)
def open_file(filename):
file = FileManager(filename)
return file
with open_file('readme.txt') as managed_file:
text = managed_file.read()
print(text)
می توانید ببینید که نکته کلیدی که باید به خاطر بسپارید این است که
- شیء به
withبیانیه باید داشته باشد__enter__و__exit__مواد و روش ها. - این
__enter__متد باید منبعی را که قرار است در آن استفاده شود برگرداندwithمسدود کردن.
مهم: نکات ظریفی وجود دارد که من از آن صرف نظر کردم تا بحث را به نقطه اصلی تبدیل کنم. برای مشخصات دقیق این روش های جادویی، به مستندات پایتون مراجعه کنید اینجا.
استفاده کردن _contextlib_
این ذن پایتون – اصل راهنمای پایتون به عنوان فهرستی از کلمات قصار – بیان می کند:
“ساده بهتر از پیچیده است”
برای اینکه واقعاً این نقطه را به خانه هدایت کند، توسعه دهندگان پایتون کتابخانه ای به نام ایجاد کرده اند contextlib حاوی ابزارهای مفید در مورد مدیران زمینه، گویی که مشکل مدیریت منابع را به اندازه کافی ساده نکرده اند. ما در اینجا تنها یکی از آنها را به طور خلاصه نشان می دهیم، اما توصیه می کنیم برای اطلاعات بیشتر، اسناد رسمی پایتون را بررسی کنید.
from contextlib import contextmanager
@contextmanager
def open_file(filename):
opened_file = open(filename)
try:
yield opened_file
finally:
opened_file.close()
مانند کد بالا، ما به سادگی می توانیم تابعی را تعریف کنیم که yieldمنبع حفاظت شده در a try بیانیه، بسته شدن آن در بعد finally بیانیه. راه دیگری برای درک آن:
- تمام مطالبی که در غیر این صورت در آن قرار می دادید
__enter__روش، به جزreturnبیانیه، قبل ازtryاینجا را مسدود کنید – اساساً دستورالعمل باز کردن منبع. - به جای برگرداندن منبع، شما
yieldآن، داخل atryمسدود کردن. - محتویات
__exit__روش به داخل مربوطه می رودfinallyمسدود کردن.
وقتی چنین عملکردی داشتیم، می توانیم با استفاده از آن آن را تزئین کنیم contextlib.contextmanager دکوراتور و ما خوب هستیم:
with open_file('readme.txt') as managed_file:
text = managed_file.read()
print(text)
همانطور که می بینید، تزئین شده است open_file تابع یک مدیر زمینه را برمی گرداند و ما می توانیم مستقیماً از آن استفاده کنیم. این به ما امکان میدهد به همان اثری که ایجاد میکنیم دست پیدا کنیم FileManager کلاس، بدون هیچ زحمتی.
نتیجه
اگر مشتاق هستید و می خواهید درباره مدیران زمینه بیشتر بخوانید، توصیه می کنم پیوندهای زیر را بررسی کنید:
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-25 09:38:06

