فصل پانزدهم آموزش پایتون مقدماتی - ماژول ها (انتشار: 1402/08/04)

ماژول‌‌ها در پایتون، به ما این اجازه را می‌‌دهند که به صورت منطقی، کدهای خود را سازماندهی‌‌کنیم. دسته‌‌بندی کدهای مربوط به‌‌هم، در یک ماژول باعث می‌‌شود که کدها به راحتی درک و استفاده شوند. از آن جایی که هر ماژول، یک شی بوده و نام ویژگی‌‌های آن، به دلخواه انتخاب می‌‌شود، به راحتی می‌‌توان آن‌‌ها را مقیّد‌‌نموده و ارجاع‌‌داد.

این چیه؟

به طور ساده‌‌تر می‌‌توان گفت، هر ماژول، شامل فایلی از کدهاست که می‌‌تواند تابع، کلاس و متغیرهای خاص خود را داشته‌‌باشد. همچنین یک ماژول می‌‌تواند حاوی کد‌‌های قابل اجرا نیز باشد.

برای نام‌‌گذاری فایلی که کدهای ماژول در آن قرار دارند، از پسوند py استفاده می‌‌شود. شکل (15-1)، مثالی ساده‌‌ای از کدهای یک ماژول با نام support.py را نشان می‌‌دهد که تنها حاوی یک تابع برای چاپ مقدار وارد ‌‌شده است.

پایتون-شکل1-15

15-1- دستور Import

به وسیله‌‌ی این دستور می‌‌توان هر فایل پایتون را در فایل دیگر آن، وارد کرد. با ورود یک ماژول به برنامه، می‌‌توان از توابع، کلاس‌‌ها و سایر محتوای آن استفاده‌‌نمود. در شکل (15-2) شمای کلی دستور را مشاهده می‌‌کنید.

پایتون-شکل2-15

زمانی که مترجم پایتون، با یک دستور import مواجه می‌‌شود، در صورت وجود ماژول مدنظر در مسیر جستجو، آن را وارد می‌‌کند. مسیر جستجو، لیستی از پوشه‌‌هایی است که مترجم، قبل از وارد‌‌کردن یک ماژول، آن را جستجو می‌‌کند. برای مثال، برای ورود ماژول support.py باید همانند شکل (15-3)، دستور import را در بالای کدهای خود قرار‌‌ دهیم. با توجه به کدهای این ماژول، خروجی مثال ما برابر با شکل (15-4) خواهدبود.

پایتون-شکل3-15
پایتون-شکل4-15

ذکر این نکته ضروری‌‌است که هر ماژول، تنها یک بار بارگذاری می‌‌شود. حتی اگر چندین بار از دستور import برای یک ماژول استفاده‌‌کنیم، از ورودهای تکراری جلوگیری می‌‌شود.

15-2- دستور From … Import

دستور from به شما اجازه می‌‌دهد تا ویژگی خاصی از یک ماژول را وارد ‌‌کنید. این دستور در جهت کاهش پردازش و جلوگیری از ورود کل ماژول‌‌هایی که دارای تعداد زیادی ویژگی هستند، کاربرد دارد. شمای کلی این دستور به صورت شکل (15-5) است.

پایتون-شکل5-15

در شکل (15-6)، می‌‌خواهیم ویژگی فیبوناچیرا از ماژول fib وارد ‌‌کنیم. همان طوری که به آن اشاره‌‌کردیم، این دستور، کل ماژول را به فضای اسمی برنامه‌‌ی ما اضافه نمی‌‌کند، بلکه فقط ویژگی فیبوناچی را به عنوان جدول سراسری نماد اضافه می‌‌کند تا به راحتی بتوان آن را فراخوانی‌‌کرده و استفاده‌‌نمود.

پایتون-شکل6-15

همچنین به وسیله‌‌ی دستور شکل (15-7) می‌‌توانیم همه اسامی موجود در ماژول را به فضای اسمی برنامه‌‌ی خود اضافه‌‌کنیم.

پایتون-شکل7-15

با وجود این که روش ذکر‌‌شده، یک راه آسان برای واردکردن تمامی اسامی ماژول، به فضای اسمی فعلی‌‌است، بایستی خیلی کم و با احتیاط از آن استفاده‌‌نمود.

15-3- مکان‌‌یابی ماژول

وقتی شما یک ماژول را وارد می‌‌کنید، مترجم پایتون، یکی از این مسیرها را برای یافتن آن جستجو می‌‌کند.

  • پوشه‌‌ی جاری که فایل اصلی برنامه در آن قرار ‌‌دارد.
  • اگر ماژول پیدا‌‌ نشد، پایتون تمامی پوشه‌‌هایی را که در متغیر پوسته به نام PYTHONPATH است، جستجو می‌‌کند. در مورد این متغیر، در بخش بعدی توضیح می‌‌دهیم.
  • در نهایت پایتون، پوشه‌‌ی پیش فرض را جستجو می‌‌کند. در سیستم‌‌عامل یونیکس، مسیر این پوشه به صورت /usr/local/bin/python/ است. این مسیر را در بالای اکثر مثال‌‌های کتاب مشاهده‌‌کردیم. همچنین این پوشه در سیستم‌‌عامل ویندوز در یکی از مسیرهای C:\Python36 ویا
    C:\Users\(AccountName)\AppData\Local\Programs\Python\Python36 قرار ‌‌دارد. البته نسخه 3.6 پایتون در این مسیردهی مدنظر قرارگرفت.

گفتنی‌‌است که تمامی مسیرهای جستجوی ماژول در یک متغیر واقع در ماژول سیستمی به نام sys.pth ذخیره می‌‌شود. متغیرهای موجود در این فایل، حاوی مسیر جاری، PYTHONPATH و مسیر پیش فرض نصب پایتون است.

15-4- متغیر PYTHONPATH

یک متغیر محیطی‌‌است که آن را در فصل‌‌های قبلی توضیح‌‌دادیم. شمای کلی تعریف این مسیر در متغیر محیطی برای دو نوع سیستم‌‌عامل ویندوز و یونیکس را به ترتیب در شکل‌‌های (15-8) و (15-9) نشان می‌‌دهیم.

پایتون-شکل8-15
پایتون-شکل9-15

15-5- فضای اسمی و حوزه‌‌ی دسترسی

متغیرها، همان نام و شناسه‌‌هایی هستند که به اشیای مختلف، نگاشت می‌‌شوند. فضای اسمی، نوع خاصی از دیکشنری‌‌است که اسامی متغیرها به عنوان کلید دیکشنری و اشیای مربوط به متغیر، معادل مقادیر آن هستند.

هر دستور پایتون می‌‌تواند به متغیرهای فضای اسمی محلی دسترسی داشته‌‌باشد. اگر دو متغیر عمومی و محلی، اسامی یکسانی داشته‌‌باشند، متغیر محلی بر متغیر سراسری، اولویت خواهد داشت.

هر تابعی دارای فضای اسمی مخصوص به خود است. متدهای هر کلاس از قوانین حوزه‌‌ی دسترسی توابع استاندارد، تبعیت می‌‌کنند.

در رابطه با این که یک متغیر محلی است ویا سراسری، پایتون حدس‌‌های آموزش دیده‌‌ای را دارد. این مترجم، فکر خواهد کرد که تمامی متغیرهای تعریف‌‌شده، در داخل بدنه‌‌ی تابع، از نوع محلی هستند. بنابراین برای انتصاب یک مقدار به متغیر سراسری در یک تابع، ابتدا باید از دستور global و به دنبال آن، نام متغیر استفاده‌‌نماییم. این دستور، به پایتون اعلام می‌‌کند که جستجوی این متغیر را در فضای اسمی محلی متوقف‌‌کند.

به عنوان مثال، در شکل (15-10) یک متغیر به نام Money را تعریف‌‌کردیم. از آن جایی که درون تابع، مقداری را به آن متغیر انتصاب‌‌دادیم، پایتون آن را به عنوان متغیر محلی درنظر می‌‌گیرد. مشکل این جا به وجود می‌‌آید که ما می‌‌خواهیم بدون انتصاب مقدار اولیه به این متغیر محلی، به آن دسترسی‌‌داشته و مقداری را به آن بیافزاییم. بنابراین در خروجی، با خطای ناخواسته‌‌ی محلی مواجه خواهیم‌‌شد.

پایتون-شکل10-15

بعد از اجرای این مثال، بعد از انتصاب مقدار اولیه به متغیر Money، دستور چاپ خارج از بدنه‌‌ی تابع، اجرا‌‌شده و مقدار اولیه را برمی‌‌گرداند. حال تابع AddMoney فراخوانی می‌‌شود. ابتدا با استفاده از کلمه کلیدی global، متغیر خارج از تابع فراخوانده‌‌شده و مقداری به آن افزوده می‌‌شود. در نهایت، مقدار جدید چاپ و در خروجی ظاهر می‌‌شود.

15-6- تابع Dir

این تابع توکار، لیستی مرتب‌‌شده از رشته‌‌های حاوی نام‌‌های تعریف‌‌شده توسط یک ماژول را برمی‌‌گرداند. این لیست شامل نام همه‌‌ی ماژول‌‌ها، متغیرها و توابعی‌‌است که در یک ماژول تعریف شده‌‌اند. شکل (15-11)، مثال ساده‌‌ای از این کاربرد را نشان می‌‌دهد.

پایتون-شکل11-15

در این مثال، ما تمامی توابع موجود در ماژول math را لیست‌‌کردیم که خروجی این قطعه کد را در شکل (15-12) مشاهده می‌‌کنید.

پایتون-شکل12-15

در این جا، متغیرهای خاص __name__ معادل نام ماژول و __file__ نام فایلی است که ماژول، از آن بارگذاری شده‌‌است.

15-7- توابع Globals و Locals

بسته به موقعیت مکانی که این توابع فراخوانی می‌‌شوند، می‌‌توانند برای بازگرداندن نام‌‌های محلی و سراسری استفاده‌‌شوند. اگر تابع ( ) locals از داخل یک تابع صدا زده شود، می‌‌تواند تمامی اسامی که از آن تابع به صورت محلی قابل دسترسی هستند را بازگرداند. و اگر ( ) globals از داخل یک تابع فراخوانی‌‌شود، می‌‌تواند تمامی اسامی که از آن تابع به صورت سراسری در دسترس‌‌باشند را بر‌‌گرداند. نوع بازگشتی هر دو توابع، از نوع دیکشنری است. از این رو می‌‌توان اسامی را با استفاده از تابع ( ) key استخراج‌‌نمود.

15-8- تابع Reload

زمانی که ماژول، به یک برنامه وارد شد، کدهای سطح بالای آن، فقط یک‌‌بار اجرا می‌‌شود. اگر می‌‌خواهید در یک ماژول، دوباره از کدهای سطح بالا استفاده‌‌کنید، به راحتی می‌‌توانید از تابع reload استفاده‌‌نمایید. بنابراین این دستور، تابع ماژول وارد‌‌شده‌‌ی قبلی را دوباره وارد می‌‌کند. شمای کلی این تابع به صورت شکل (15-13) می‌‌باشد.

پایتون-شکل13-15

لازم به ذکر است که برای پایتون نسخه 3 بایستی ماژول importlib نیز فراخوانی گردد.

15-9- بسته‌‌ها در پایتون

هر بسته از یک ساختار سلسله مراتبی فایل و پوشه پیروی می‌‌کند. محیط کاربردی برنامه پایتون، شامل ماژول‌‌ها، زیربسته‌‌ها و زیر ِزیربسته‌‌ها و از این قبیل است. فرض‌‌کنید یک فایل Pots.py در داخل پوشه Phone وجود ‌‌داشته و حاوی کدهای شکل (15-14) باشد.

پایتون-شکل14-15

به همین ترتیب، دو فایل دیگر با نام‌‌های Isdn.py و G3.py حاوی توابعی با نام‌‌های Isdn و G3 خواهیم‌‌داشت. حال یک فایل دیگر با نام __init__.py داخل این پوشه ایجاد می‌‌کنیم. برای این که در موقع ورود Phone، تمامی توابع در دسترس‌‌باشند، بایستی از دستور ورود صریح، به صورت شکل (15-15) استفاده‌‌نماییم.

پایتون-شکل15-15

پس از اضافه‌‌کردن این خطوط به __init__.py، در زمان وارد‌‌کردن بسته Phone، همه‌‌ی این کلاس‌‌ها در دسترس خواهندبود. نمونه‌‌ای از کاربرد این مطالب را در مثال شکل (15-16) خواهیددید.

پایتون-شکل16-15

زمانی که این قطعه کد اجرا شود، خروجی آن به شکل (15-17) می‌‌شود.

پایتون-شکل17-15

در این مثال، ما تنها یک تابع را برای هر فایل درنظر گرفتیم. اما شما می‌‌توانید چندین تابع مختلف را در فایل‌‌های خود داشته‌‌باشید. البته هر فایل می‌‌تواند حاوی کلاس‌‌های متعددی نیز باشد. بنابراین در نهایت می‌‌توانید بسته‌‌های خود را از این کلاس‌‌ها استخراج‌‌کنید.

 

 

در پست بعدی به فایل و دایرکتوری خواهیم پرداخت. با ما همراه باشین.


نظرات خوانندگان نوشته


نظری در این مورد دارید؟ خوشحال می‌شیم اون رو برامون ارسال کنید.