آموزش پایتون - ماژول‌ها

ماژول‌ها در پایتون

مفهوم ماژول در پایتون ماژولار بودن برنامه‌ها را بیش از پیش ارتقا می‌دهد. شما می‌توانید چند تابع مرتبط را کنار هم تعریف کرده و توابع مورد نیاز خود را بارگذاری کنید. ماژول فایلی حاوی تعریف توابع، کلاس‌ها، متغیرها، ثابت‌ها یا هر شیء دیگری در پایتون است. محتوای این فایل می‌تواند در اختیار هر برنامه دیگری قرار گیرد. پایتون برای این منظور از کلمه کلیدی import استفاده می‌کند.

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

مثالی از ماژول در پایتون

import math
print ("Square root of 100:", math.sqrt(100))

کد بالا خروجی زیر را تولید خواهد کرد −

Square root of 100: 10.0

ماژول‌های داخلی پایتون

کتابخانه استاندارد پایتون همراه با تعداد زیادی ماژول ارائه می‌شود. به این ماژول‌ها، ماژول‌های داخلی (Built-in) می‌گویند. بیشتر این ماژول‌های داخلی به زبان C نوشته شده‌اند (زیرا پیاده‌سازی مرجع پایتون به زبان C است) و از قبل در کتابخانه کمپایل شده‌اند. این ماژول‌ها قابلیت‌های کاربردی فراوانی مانند مدیریت سیستم‌عامل، ورودی/خروجی دیسک، شبکه و غیره را پوشش می‌دهند.

در ادامه فهرستی انتخابی از ماژول‌های داخلی آورده شده است −

شماره نام و توضیحات کوتاه

1

os

این ماژول یک رابط یکپارچه برای دسترسی به تعدادی از توابع سیستم‌عامل فراهم می‌کند.

2

string

این ماژول شامل توابع متعددی برای پردازش رشته‌ها است.

3

re

این ماژول مجموعه‌ای از امکانات قدرتمند عبارت‌های باقاعده (Regular Expression) را ارائه می‌دهد. عبارت باقاعده (RegEx) امکان جستجو و تطبیق قدرتمند الگوی خاصی در رشته‌ها را فراهم می‌سازد.

4

math

این ماژول عملیات ریاضی مختلفی را برای اعداد ممیز شناور پیاده‌سازی می‌کند. این توابع معمولاً رابط‌های سبکی حول توابع کتابخانه‌ای C سیستم‌عامل هستند.

5

cmath

این ماژول شامل مجموعه ای از عملیات ریاضی برای اعداد مختلط است.

6

datetime

این ماژول توابعی برای کار با تاریخ و زمان در طول روز ارائه می‌دهد و کتابخانه زمان اجرای C را پوشش می‌دهد.

7

gc

این ماژول رابطی برای زباله‌روب (Garbage Collector) داخلی پایتون فراهم می‌سازد.

8

asyncio

این ماژول قابلیت‌های لازم برای پردازش ناهمگام (Asynchronous) را تعریف می‌کند.

9

Collections

این ماژول انواع داده‌های نگه‌دارنده (Container) پیشرفته را ارائه می‌دهد.

10

functools

این ماژول دارای توابع مرتبه‌بالا و عملیات روی اشیاء قابل فراخوانی است که در برنامه‌نویسی تابعی کاربرد دارند.

11

operator

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

12

pickle

برای تبدیل اشیاء پایتون به جریان بایت‌ها (Byte Streams) و برعکس استفاده می‌شود.

13

socket

رابط شبکه سطح پایین را فراهم می‌کند.

14

sqlite3

یک پیاده‌سازی از استاندارد DB-API 2.0 با استفاده از SQLite 3.x.

15

statistics

توابع آمار ریاضی را ارائه می‌دهد.

16

typing

پشتیبانی از راهنمای نوع‌ها (Type Hints) را فراهم می‌کند.

17

venv

برای ایجاد محیط‌های مجازی (Virtual Environments) به کار می‌رود.

18

json

برای کدگذاری و رمزگشایی فرمت JSON استفاده می‌شود.

19

wsgiref

ابزارها و پیاده‌سازی مرجع WSGI را ارائه می‌دهد.

20

unittest

فریم‌ورک تست واحد (Unit Testing) برای پایتون.

21

random

تولید اعداد شبه‌تصادفی.

22

sys

توابعی ارائه می‌دهد که تعامل مستقیمی با مفسر پایتون دارند.

23

requests

درخواست‌های HTTP را با ارائه رابطی کاربرپسند برای ارسال و مدیریت پاسخ‌ها ساده می‌کند.

24

itertools

یک شیء تکرارکننده (Iterator) برای پیمایش در مجموعه‌ها (مانند لیست، تاپل و غیره) استفاده می‌شود. این ماژول ابزارهای مختلفی را برای ساخت و دستکاری تکرارکننده‌ها فراهم می‌کند.

25

locale

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

ماژول‌های تعریف‌شده توسط کاربر در پایتون

هر فایل متنی با پسوند .py که حاوی کد پایتون باشد، اساساً یک ماژول است. این فایل می‌تواند شامل تعاریف یک یا چند تابع، متغیر، ثابت و همچنین کلاس باشد. هر شیء پایتون از یک ماژول می‌تواند با استفاده از دستور import در اختیار جلسه مفسر یا اسکریپت دیگر پایتون قرار گیرد. یک ماژول همچنین می‌تواند شامل کدهای قابل اجرا باشد.

ایجاد یک ماژول پایتون

ایجاد یک ماژول چیزی جز ذخیره کردن کد پایتون با کمک هر ویرایشگری نیست. بیایید کد زیر را با نام mymodule.py ذخیره کنیم.

def SayHello(name):
   print ("Hi {}! How are you?".format(name))
   return

اکنون می‌توانید mymodule را در ترمینال فعلی پایتون وارد (import) کنید.

>>> import mymodule
>>> mymodule.SayHello("Harish")
Hi Harish! How are you?

همچنین می‌توانید یک ماژول را در اسکریپت دیگری از پایتون فراخوانی کنید. کد زیر را با نام example.py ذخیره کنید:

import mymodule
mymodule.SayHello("Harish")

این اسکریپت را از ترمینال خط فرمان اجرا کنید:

Hi Harish! How are you?

دستور import

در پایتون، کلمه کلیدی import برای بارگذاری یک شیء پایتون از یک ماژول ارائه شده است. این شیء می‌تواند یک تابع، کلاس، متغیر و غیره باشد. اگر یک ماژول شامل چندین تعریف باشد، همه آن‌ها در فضای نام (Namespace) بارگذاری خواهند شد.

بیایید کد زیر را که دارای سه تابع است با نام mymodule.py ذخیره کنیم.

def sum(x,y):
   return x+y

def average(x,y):
   return (x+y)/2

def power(x,y):
   return x**y

دستور import mymodule تمام توابع موجود در این ماژول را در فضای نام فعلی بارگذاری می‌کند. هر تابع در ماژول واردشده، یک ویژگی (Attribute) از شیء آن ماژول محسوب می‌شود.

>>> dir(mymodule)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'average', 'power', 'sum']

برای فراخوانی هر تابع، از ارجاع شیء ماژول استفاده کنید. به عنوان مثال، ()mymodule.sum.

import mymodule
print ("sum:",mymodule.sum(10,20))
print ("average:",mymodule.average(10,20))
print ("power:",mymodule.power(10, 2))

این کد خروجی زیر را تولید خواهد کرد −

sum:30
average:15.0
power:100

دستور from ... import

دستور import تمام منابع ماژول را در فضای نام فعلی بارگذاری می‌کند. با این حال، با استفاده از این ساختار می‌توان اشیاء خاصی را از یک ماژول وارد کرد. به عنوان مثال −

از میان سه تابع موجود در mymodule، تنها دو تابع در اسکریپت قابل اجرای example.py وارد شده‌اند:

from mymodule import sum, average
print ("sum:",sum(10,20))
print ("average:",average(10,20))

کد بالا خروجی زیر را تولید خواهد کرد −

sum: 30
average: 15.0

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

دستور * from...import

همچنین امکان وارد کردن تمام نام‌ها از یک ماژول به فضای نام فعلی با استفاده از دستور import زیر وجود دارد −

from modname import *

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

دستور import ... as

شما می‌توانید یک نام مستعار (Alias) به ماژول واردشده اختصاص دهید.

from modulename as alias

هنگام فراخوانی تابع، باید نام مستعار را پیش از نام تابع قرار دهید.

به مثال زیر توجه کنید −

import mymodule as x
print ("sum:",x.sum(10,20))
print ("average:", x.average(10,20))
print ("power:", x.power(10, 2))

مکان‌یابی ماژول‌ها

هنگامی که یک ماژول را وارد می‌کنید، مفسر پایتون ماژول را با ترتیب زیر جستجو می‌کند −

  • دایرکتوری فعلی.

  • اگر ماژول پیدا نشد، پایتون تک‌تک دایرکتوری‌های موجود در متغیر شل PYTHONPATH را جستجو می‌کند.

  • اگر همه موارد بالا ناموفق بود، پایتون مسیر پیش‌فرض را بررسی می‌کند. در یونیکس، این مسیر پیش‌فرض معمولاً /usr/local/lib/python/ است.

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

متغیر PYTHONPATH

متغیر PYTHONPATH یک متغیر محیطی است که از فهرستی از دایرکتوری‌ها تشکیل شده است. ساختار نوشتاری PYTHONPATH مانند متغیر شل PATH است.

در ادامه یک نمونه типиک از PYTHONPATH در سیستم‌عامل ویندوز آورده شده است −

set PYTHONPATH = c:\python20\lib;

و این هم یک نمونه PYTHONPATH در سیستم‌عامل یونیکس −

set PYTHONPATH = /usr/local/lib/python

فضای نام و حوزه متغیرها (Scoping)

متغیرها نام‌هایی (شناسه‌هایی) هستند که به اشیاء نگاشت می‌شوند. یک فضای نام (Namespace)، دیکشنری از نام‌های متغیرها (کلیدها) و اشیاء مربوط به آن‌ها (مقادیر) است.

  • یک دستور پایتون می‌تواند به متغیرها در فضای نام محلی (Local) و فضای نام سراسری (Global) دسترسی داشته باشد. اگر یک متغیر محلی و یک متغیر سراسری نام یکسانی داشته باشند، متغیر محلی روی متغیر سراسری سایه می‌اندازد (آن را پوشش می‌دهد).

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

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

  • برای مقداردهی به یک متغیر سراسری در داخل یک تابع، ابتدا باید از دستور global استفاده کنید.

  • دستور global VarName به پایتون می‌گوید که VarName یک متغیر سراسری است. به این ترتیب پایتون جستجوی فضای نام محلی را برای آن متغیر متوقف می‌کند.

مثال

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

Money = 2000
def AddMoney():
   # Uncomment the following line to fix the code:
   # global Money
   Money = Money + 1
print (Money)
AddMoney()
print (Money)

ویژگی‌های ماژول (Module Attributes)

در پایتون، یک ماژول شیئی از کلاس ماژول است و بنابراین توسط ویژگی‌ها (Attributes) مشخص می‌شود.

ویژگی‌های ماژول به شرح زیر هستند −

  • ویژگی __file__ نام فیزیکی ماژول را برمی‌گرداند.

  • ویژگی __package__ پکیجی را که ماژول به آن تعلق دارد برمی‌گرداند.

  • ویژگی __doc__ رشته مستندات (Docstring) بالای ماژول را در صورت وجود برمی‌گرداند.

  • ویژگی __dict__ کل حوزه (Scope) ماژول را برمی‌گرداند.

  • ویژگی __name__ نام ماژول را برمی‌گرداند.

مثال

با فرض اینکه کد زیر با نام mymodule.py ذخیره شده است −

"The docstring of mymodule"
def sum(x,y):
   return x+y

def average(x,y):
   return (x+y)/2
   
def power(x,y):
   return x**y

بیایید ویژگی‌های mymodule را با وارد کردن آن در اسکریپت زیر بررسی کنیم −

import mymodule

print ("__file__ attribute:", mymodule.__file__)
print ("__doc__ attribute:", mymodule.__doc__)
print ("__name__ attribute:", mymodule.__name__)

این کد خروجی زیر را تولید خواهد کرد −

__file__ attribute: C:\math\examples\mymodule.py
__doc__ attribute: The docstring of mymodule
__name__ attribute: mymodule

ویژگی __name__

ویژگی __name__ در ماژول پایتون اهمیت بالایی دارد. بیایید آن را با جزئیات بیشتری بررسی کنیم.

در یک شل تعاملی، ویژگی __name__ مقدار 'main__' را برمی‌گرداند:

>>> __name__
'__main__'

اگر ماژولی را در جلسه مفسر وارد کنید، نام آن ماژول را به عنوان ویژگی __name__ آن ماژول برمی‌گرداند.

>>> import math
>>> math.__name__
'math'

از داخل یک اسکریپت پایتون، ویژگی __name__ مقدار 'main__' را برمی‌گرداند:

#example.py
print ("__name__ attribute within a script:", __name__)

این را در ترمینال خط فرمان اجرا کنید −

__name__ attribute within a script: __main__

این ویژگی به اسکریپت پایتون اجازه می‌دهد هم به عنوان یک برنامه قابل اجرا و هم به عنوان یک ماژول استفاده شود. بر خلاف زبان‌هایی مانند ++C، Java، #C و غیره، در پایتون مفهومی به نام تابع ()main وجود ندارد. اسکریپت برنامه پایتون با پسوند py. می‌تواند شامل تعاریف توابع و همچنین دستورات قابل اجرا باشد.

فایل mymodule.py را با کد زیر ذخیره کنید −

"The docstring of mymodule"
def sum(x,y):
   return x+y
   
print ("sum:",sum(10,20))

می‌بینید که تابع ()sum در همان اسکریپتی که در آن تعریف شده، فراخوانی می‌شود.

sum: 30

حال بیایید این تابع را در اسکریپت دیگری به نام example.py وارد کنیم.

import mymodule
print ("sum:",mymodule.sum(10,20))

این کد خروجی زیر را تولید خواهد کرد −

sum: 30
sum: 30

خروجی "sum:30" دو بار ظاهر می‌شود. یک بار زمانی که ماژول mymodule وارد می‌شود؛ چرا که دستورات قابل اجرا در ماژول واردشده نیز اجرا می‌شوند. خروجی دوم مربوط به اسکریپت فراخوان، یعنی برنامه example.py است.

آنچه ما می‌خواهیم اتفاق بیفتد این است که هنگام وارد کردن یک ماژول، فقط تابع وارد شود و دستورات قابل اجرای آن اجرا نشوند. این کار را می‌توان با بررسی مقدار __name__ انجام داد. اگر مقدار آن __main__ باشد، به این معنی است که فایل مستقیماً اجرا شده و وارد (import) نشده است. دستورات قابل اجرا مانند فراخوانی توابع را به صورت شرطی قرار دهید.

دستور if را مطابق شکل زیر به mymodule.py اضافه کنید −

"The docstring of mymodule"
def sum(x,y):
   return x+y

if __name__ == "__main__":
   print ("sum:",sum(10,20))

اکنون اگر برنامه example.py را اجرا کنید، خواهید دید که خروجی sum:30 فقط یک بار ظاهر می‌شود.

sum: 30

تابع ( )dir

تابع داخلی ()dir در پایتون، لیستی مرتب‌شده از رشته‌ها شامل نام‌های تعریف‌شده توسط یک ماژول را برمی‌گرداند.

این لیست شامل نام تمام ماژول‌ها، متغیرها و توابعی است که در یک ماژول تعریف شده‌اند. در ادامه یک مثال ساده آورده شده است −

# Import built-in module math
import math

content = dir(math)
print (content)

هنگامی که کد بالا اجرا می‌شود، نتیجه زیر را تولید می‌کند −

['__doc__', '__file__', '__name__', 'acos', 'asin', 'atan', 
'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 
'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log',
'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 
'sqrt', 'tan', 'tanh']

تابع ()reload

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

فرض کنید یک ماژول تست (test.py) با تابع زیر داریم −

def SayHello(name):
   print ("Hi {}! How are you?".format(name))
   return

می‌توانیم ماژول را وارد کرده و تابع آن را از محیط پایتون به صورت زیر فراخوانی کنیم −

>>> import test
>>> test.SayHello("Deepak")
Hi Deepak! How are you?

با این حال، فرض کنید لازم است تابع ()SayHello را تغییر دهید، مانند −

def SayHello(name, course):
   print ("Hi {}! How are you?".format(name))
   print ("Welcome to {} Tutorial by Tut24".format(course))
   return

حتی اگر فایل test.py را ویرایش کرده و ذخیره کنید، تابع بارگذاری‌شده در حافظه به‌روزرسانی نمی‌شود. شما باید آن را با استفاده از تابع ()reload در ماژول imp بارگذاری مجدد کنید.

>>> import imp
>>> imp.reload(test)
>>> test.SayHello("Deepak", "Python")
Hi Deepak! How are you?
Welcome to Python Tutorial by Tut24

پکیج‌ها در پایتون

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

فایل Pots.py موجود در دایرکتوری Phone را در نظر بگیرید. این فایل دارای خط کد زیر است −

def Pots():
   print "I'm Pots Phone"

به همین ترتیب، دو فایل دیگر با توابع مختلف اما همنام با تابع بالا داریم −

  • فایل Phone/Isdn.py دارای تابع ()Isdn

  • فایل Phone/G3.py دارای تابع ()G3

حال، یک فایل دیگر به نام init__.py__ در دایرکتوری Phone ایجاد کنید −

  • Phone/__init__.py

برای اینکه هنگام وارد کردن Phone تمامی توابع شما در دسترس باشند، باید دستورات صریح import را در init__.py__ به صورت زیر قرار دهید −

from Pots import Pots
from Isdn import Isdn
from G3 import G3

پس از افزودن این خطوط به init__.py__، با وارد کردن پکیج Phone تمام این کلاس‌ها در دسترس شما خواهند بود.

# Now import your Phone Package.
import Phone

Phone.Pots()
Phone.Isdn()
Phone.G3()

هنگامی که کد بالا اجرا می‌شود، نتیجه زیر را تولید می‌کند −

I'm Pots Phone
I'm 3G Phone
I'm ISDN Phone

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

پیشرفت مطالعه: وضعیت خوانده‌شدن این درس فقط در همین مرورگر ذخیره می‌شود؛ بدون نیاز به حساب کاربری.