سلام دوستان
با ادامه ی کتاب پایتون مقدماتی که به همراه دوست عزیزم جناب مهندس مهدی عباسپور شاهمرس نوشته و چاپ کردیم در خدمتتون هستیم.
ماژولها در پایتون، به ما این اجازه را میدهند که به صورت منطقی، کدهای خود را سازماندهیکنیم. دستهبندی کدهای مربوط بههم، در یک ماژول باعث میشود که کدها به راحتی درک و استفاده شوند. از آن جایی که هر ماژول، یک شی بوده و نام ویژگیهای آن، به دلخواه انتخاب میشود، به راحتی میتوان آنها را مقیّدنموده[1] و ارجاعداد.
به طور سادهتر میتوان گفت، هر ماژول، شامل فایلی از کدهاست که میتواند تابع، کلاس و متغیرهای خاص خود را داشتهباشد. همچنین یک ماژول میتواند حاوی کدهای قابل اجرا نیز باشد.
برای نامگذاری فایلی که کدهای ماژول در آن قرار دارند، از پسوند py استفاده میشود. شکل (15-1)، مثالی سادهای از کدهای یک ماژول با نام support.py را نشان میدهد که تنها حاوی یک تابع برای چاپ مقدار وارد شده است.
[1]Bind
به وسیلهی این دستور میتوان هر فایل پایتون را در فایل دیگر آن، وارد کرد. با ورود یک ماژول به برنامه، میتوان از توابع، کلاسها و سایر محتوای آن استفادهنمود. در شکل (15-2) شمای کلی دستور را مشاهده میکنید.
زمانی که مترجم پایتون، با یک دستور import مواجه میشود، در صورت وجود ماژول مدنظر در مسیر جستجو، آن را وارد میکند. مسیر جستجو، لیستی از پوشههایی است که مترجم، قبل از واردکردن یک ماژول، آن را جستجو میکند. برای مثال، برای ورود ماژول support.py باید همانند شکل (15-3)، دستور import را در بالای کدهای خود قرار دهیم. با توجه به کدهای این ماژول، خروجی مثال ما برابر با شکل (15-4) خواهدبود.
ذکر این نکته ضروریاست که هر ماژول، تنها یک بار بارگذاری[1] میشود. حتی اگر چندین بار از دستور import برای یک ماژول استفادهکنیم، از ورودهای تکراری جلوگیری میشود.
[1]Load
دستور from به شما اجازه میدهد تا ویژگی خاصی از یک ماژول را وارد کنید. این دستور در جهت کاهش پردازش و جلوگیری از ورود کل ماژولهایی که دارای تعداد زیادی ویژگی هستند، کاربرد دارد. شمای کلی این دستور به صورت شکل (15-5) است.
در شکل (15-6)، میخواهیم ویژگی فیبوناچیرا از ماژول fib وارد کنیم. همان طوری که به آن اشارهکردیم، این دستور، کل ماژول را به فضای اسمی برنامهی ما اضافه نمیکند، بلکه فقط ویژگی فیبوناچی را به عنوان جدول سراسری نماد[1]اضافه میکند تا به راحتی بتوان آن را فراخوانیکرده و استفادهنمود.
همچنین به وسیلهی دستور شکل (15-7) میتوانیم همه اسامی موجود در ماژول را به فضای اسمی برنامهی خود اضافهکنیم.
با وجود این که روش ذکرشده، یک راه آسان برای واردکردن تمامی اسامی ماژول، به فضای اسمی فعلیاست، بایستی خیلی کم و با احتیاط از آن استفادهنمود.
[1]Global Symbol Table
وقتی شما یک ماژول را وارد میکنید، مترجم پایتون، یکی از این مسیرها را برای یافتن آن جستجو میکند.
گفتنیاست که تمامی مسیرهای جستجوی ماژول در یک متغیر واقع در ماژول سیستمی به نام sys.pth ذخیره میشود. متغیرهای موجود در این فایل، حاوی مسیر جاری، PYTHONPATH و مسیر پیش فرض نصب پایتون است.
[1]Shell Variable
یک متغیر محیطیاست که آن را در فصلهای قبلی توضیحدادیم. شمای کلی تعریف این مسیر در متغیر محیطی برای دو نوع سیستمعامل ویندوز و یونیکس را به ترتیب در شکلهای (15-8) و (15-9) نشان میدهیم.
متغیرها، همان نام و شناسههایی هستند که به اشیای مختلف، نگاشت میشوند. فضای اسمی، نوع خاصی از دیکشنریاست که اسامی متغیرها به عنوان کلید دیکشنری و اشیای مربوط به متغیر، معادل مقادیر آن هستند.
هر دستور پایتون میتواند به متغیرهای فضای اسمی محلی دسترسی داشتهباشد. اگر دو متغیر عمومی و محلی، اسامی یکسانی داشتهباشند، متغیر محلی بر متغیر سراسری، اولویت خواهد داشت.
هر تابعی دارای فضای اسمی مخصوص به خود است. متدهای هر کلاس از قوانین حوزهی دسترسی توابع استاندارد، تبعیت میکنند.
در رابطه با این که یک متغیر محلی است ویا سراسری، پایتون حدسهای آموزش دیدهای را دارد. این مترجم، فکر خواهد کرد که تمامی متغیرهای تعریفشده، در داخل بدنهی تابع، از نوع محلی هستند. بنابراین برای انتصاب یک مقدار به متغیر سراسری در یک تابع، ابتدا باید از دستور global و به دنبال آن، نام متغیر استفادهنماییم. این دستور، به پایتون اعلام میکند که جستجوی این متغیر را در فضای اسمی محلی متوقفکند.
به عنوان مثال، در شکل (15-10) یک متغیر به نام Money را تعریفکردیم. از آن جایی که درون تابع، مقداری را به آن متغیر انتصابدادیم، پایتون آن را به عنوان متغیر محلی درنظر میگیرد. مشکل این جا به وجود میآید که ما میخواهیم بدون انتصاب مقدار اولیه به این متغیر محلی، به آن دسترسیداشته و مقداری را به آن بیافزاییم. بنابراین در خروجی، با خطای ناخواستهی محلی[1] مواجه خواهیمشد.
بعد از اجرای این مثال، بعد از انتصاب مقدار اولیه به متغیر Money، دستور چاپ خارج از بدنهی تابع، اجراشده و مقدار اولیه را برمیگرداند. حال تابع AddMoney فراخوانی میشود. ابتدا با استفاده از کلمه کلیدی global، متغیر خارج از تابع فراخواندهشده و مقداری به آن افزوده میشود. در نهایت، مقدار جدید چاپ و در خروجی ظاهر میشود.
[1] Unbound Local Error
این تابع توکار، لیستی مرتبشده از رشتههای حاوی نامهای تعریفشده توسط یک ماژول را برمیگرداند. این لیست شامل نام همهی ماژولها، متغیرها و توابعیاست که در یک ماژول تعریف شدهاند. شکل (15-11)، مثال سادهای از این کاربرد را نشان میدهد.
در این مثال، ما تمامی توابع موجود در ماژول math را لیستکردیم که خروجی این قطعه کد را در شکل (15-12) مشاهده میکنید.
در این جا، متغیرهای خاص __name__ معادل نام ماژول و __file__ نام فایلی است که ماژول، از آن بارگذاری شدهاست.
بسته به موقعیت مکانی که این توابع فراخوانی میشوند، میتوانند برای بازگرداندن نامهای محلی و سراسری استفادهشوند. اگر تابع ( ) locals از داخل یک تابع صدا زده شود، میتواند تمامی اسامی که از آن تابع به صورت محلی قابل دسترسی هستند را بازگرداند. و اگر ( ) globals از داخل یک تابع فراخوانیشود، میتواند تمامی اسامی که از آن تابع به صورت سراسری در دسترسباشند را برگرداند. نوع بازگشتی هر دو توابع، از نوع دیکشنری است. از این رو میتوان اسامی را با استفاده از تابع ( ) key استخراجنمود.
زمانی که ماژول، به یک برنامه وارد شد، کدهای سطح بالای[1] آن، فقط یکبار اجرا میشود. اگر میخواهید در یک ماژول، دوباره از کدهای سطح بالا استفادهکنید، به راحتی میتوانید از تابع reload استفادهنمایید. بنابراین این دستور، تابع ماژول واردشدهی قبلی را دوباره وارد میکند. شمای کلی این تابع به صورت شکل (15-13) میباشد.
[1]Top-Level
لازم به ذکر است که برای پایتون نسخه 3 بایستی ماژول importlib نیز فراخوانی گردد.
هر بسته از یک ساختار سلسله مراتبی فایل و پوشه پیروی میکند. محیط کاربردی برنامه پایتون، شامل ماژولها، زیربستهها و زیر ِزیربستهها و از این قبیل است. فرضکنید یک فایل Pots.py در داخل پوشه Phone وجود داشته و حاوی کدهای شکل (15-14) باشد.
به همین ترتیب، دو فایل دیگر با نامهای Isdn.py و G3.py حاوی توابعی با نامهای Isdn و G3 خواهیمداشت. حال یک فایل دیگر با نام __init__.py داخل این پوشه ایجاد میکنیم. برای این که در موقع ورود Phone، تمامی توابع در دسترسباشند، بایستی از دستور ورود صریح[2]، به صورت شکل (15-15) استفادهنماییم.
پس از اضافهکردن این خطوط به __init__.py، در زمان واردکردن بسته Phone، همهی این کلاسها در دسترس خواهندبود. نمونهای از کاربرد این مطالب را در مثال شکل (15-16) خواهیددید.
زمانی که این قطعه کد اجرا شود، خروجی آن به شکل (15-17) میشود.
در این مثال، ما تنها یک تابع را برای هر فایل درنظر گرفتیم. اما شما میتوانید چندین تابع مختلف را در فایلهای خود داشتهباشید. البته هر فایل میتواند حاوی کلاسهای متعددی نیز باشد. بنابراین در نهایت میتوانید بستههای خود را از این کلاسها استخراجکنید.
[1]Packages [2]Explicit Import
در پست بعدی به فایل و دایرکتوری خواهیم پرداخت. با ما همراه باشین.