داریوش مهدی پور یقینی
داریوش مهدی پور یقینی
خواندن ۷ دقیقه·۲ سال پیش

فصل پانزدهم آموزش پایتون مقدماتی - ماژول ها

سلام دوستان

با ادامه ی کتاب پایتون مقدماتی که به همراه دوست عزیزم جناب مهندس مهدی عباسپور شاهمرس نوشته و چاپ کردیم در خدمتتون هستیم.

https://virgool.io/@mahdi.abbaspour.sh

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

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

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

شکل (15-1)
شکل (15-1)
[1]Bind

15-1- دستور Import

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

شکل (15-2)
شکل (15-2)

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

شکل (15-3)
شکل (15-3)
شکل (15-4)
شکل (15-4)

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

[1]Load

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

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

شکل (15-5)
شکل (15-5)

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

شکل (15-6)
شکل (15-6)

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

شکل (15-7)
شکل (15-7)

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

[1]Global Symbol Table

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

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

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

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

[1]Shell Variable

15-4- متغیر PYTHONPATH

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

شکل (15-8)
شکل (15-8)
شکل (15-9)
شکل (15-9)

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

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

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

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

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

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

شکل (15-10)
شکل (15-10)

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

[1] Unbound Local Error

15-6- تابع Dir

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

شکل (15-11)
شکل (15-11)

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

شکل (15-12)
شکل (15-12)

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

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

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

15-8- تابع Reload

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

شکل (15-13)
شکل (15-13)
[1]Top-Level

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

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

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

شکل (15-14)
شکل (15-14)

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

شکل (15-15)
شکل (15-15)

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

شکل (15-16)
شکل (15-16)

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

شکل (15-17)
شکل (15-17)

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

[1]Packages [2]Explicit Import


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

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