Python حرفه‌ای: ماژول‌های پیشفرض پایتون

Professional Python: Default Python Modules

23 اسفند 1399
درسنامه درس 21 از سری پایتون حرفه‌ای
Python حرفه ای: ماژول های پیشفرض پایتون (قسمت 21)

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

یکی از ویژگی های اصلی زبان پایتون این است که هسته آن بسیار کوچک است و تا این قسمت از این دوره آموزشی بیشتر هسته زبان پایتون را بررسی کرده ایم. محبوبیت و دلیل اصلی شهرت زبان پایتون به دلیل ماژول های خارج از هسته اصلی برنامه است. اگر به وب سایت رسمی پایتون و صفحه python module index سر بزنید متوجه تعداد بسیار زیاد این ماژول ها می شوید:

docs.python.org/3/py-modindex.html

تمامی ماژول هایی که در لیست بالا مشاهده می کنید به صورت پیش فرض و با دانلود مفسر پایتون، نصب شده اند بنابراین به همه آن ها دسترسی داریم. به طور مثال ماژولی به نام random در زبان پایتون وجود دارد که می تواند اعداد تصادفی را برای ما ایجاد کند. مثال:

import random


print(random.random())

پکیج random متدی به نام random دارد که برای ما یک عدد تصادفی بین صفر و یک را ایجاد می کند. من با اجرای این کد نتیجه زیر را گرفتم:

0.5535513123347774

اما طبیعتا نتیجه ای که شما می گیرید متفاوت خواهد بود چرا که این متد اعداد تصادفی ایجاد می کند. متد بعدی randint نام دارد که به جای تولید عدد تصادفی بین صفر و یک، عددی تصادفی را بین بازه مشخص شده توسط شما تولید می کند. مثال:

import random


print(random.randint(1, 13))

پارامتر اول نقطه شروع و پارامتر دوم نقطه پایان است بنابراین ما به دنبال عددی تصادفی بین ۱ و ۱۳ هستیم. هر بار که کد بالا را اجرا کنید نتیجه متفاوتی را خواهید گرفت (من با سه بار اجرای این کد اعداد ۳ و ۵ و ۱ را دریافت کردم). متد بعدی choice است که از بین اعضای یک لیست، یکی را به صورت تصادفی انتخاب می کند:

import random


print(random.choice([1, 3, 44, 5, 99]))

با اجرای این کد به مفسر پایتون گفته ایم که باید از بین اعضای لیست بالا، یکی را به صورت تصادفی انتخاب کند. با اجرای این کد اعداد مختلفی از اعضای این لیست را دریافت می کنید (من با اجرای کد بالا عدد ۱ و با اجرای دوباره آن ع ۴۴ را دریافت کردم). متد بعدی ما متد shuffle است که ترتیب اعضای درون یک لیست را بهم می ریزد:

import random


my_list = [1, 2, 3, 4, 5, 6]


random.shuffle(my_list)


print(my_list)

من در این کد یک لیست ساده را دارم که متد shuffle را روی آن اجرا کرده ام و با چاپ کردن دوباره shuffle نتیجه زیر را دریافت کرده ام:

[2, 1, 5, 6, 4, 3]

همانطور که می بینید ترتیب لیست دیگر مانند قبل نیست بلکه اعضای آن جا به جا شده اند.

آشنایی با PIP و نصب پکیج ها از pypi

یکی از بزرگترین دلایلی که زبان پایتون را به جایگاه امروزی خود رسانده است، وجود توسعه دهندگانی مانند من و شما است! یعنی چه؟ منظور من پکیج هایی است که به صورت پیش فرض در هسته پایتون نیستند و توسط تیم توسعه پایتون ساخته نشده اند بلکه پکیج هایی هستند که توسط توسعه دهندگان دیگر و به صورت متن باز (open source) ساخته شده اند. ما می توانیم از پکیج های دیگر توسعه دهندگان استفاده کنیم تا بهترین نتیجه را برای خودمان رقم بزنیم و به اصطلاح از اختراع دوباره چرخ جلوگیری کنیم.

زبان پایتون برای به اشتراک گذاری این کدها از PIP استفاده می کند که یک سیستم مدیریت پکیج شبیه به npm یا composer است. PIP روشی برای نصب پکیج هایی است که توسط توسعه دهندگان دیگر ساخته شده اند. به طور مثال اگر بخواهیم وب سایتی را با زبان پایتون بسازیم واقعا نیازی به کد نویسی از صفر نداریم بلکه می توانیم از پکیج های ساخته شده توسط دیگران استفاده کنیم تا سرعت توسعه بسیار بالاتر برود. مسئله اینجاست که چطور می توانیم پکیج های دیگران را پیدا کنیم؟ تیم توسعه پایتون برای حل این مشکل وب سایت pypi.org را راه اندازی کرده اند (pypi مخفف python package index است) که میزبان پکیج ها و ماژول های نوشته شده توسط دیگر توسعه دهندگان است. در زمان نگارش این مقاله چیزی حدود ۳۰۰ هزار پکیج از توسعه دهندگان مختلف بر روی این پلتفرم قرار دارد که می توانید آن ها را دانلود کرده و از آن ها استفاده کنید.

مسئله اینجاست که چطور می توانیم از پکیج های موجود در این وب سایت استفاده کنیم؟ برای آشنایی با این کار بهتر است به صورت عملی یک پکیج به نام pyjokes را دانلود کنیم:

pypi.org/project/pyjokes/

این پکیج، یک پکیج تمرینی است که جوک های انگلیسی و کوتاه را در زمینه برنامه نویسی به شما می دهد. در صورتی که به آدرس بالا بروید، صفحه پکیج pyjokes را مشاهده خواهید کرد. دستور نصب این پکیج در همان ابتدای این صفحه مشاهده می شود:

pip install pyjokes

همانطور که مشاهده می کنید، برای نصب از دستور خاصی به نام pip استفاده می کنیم. pip قسمتی از پکیج زبان پایتون است که به صورت خودکار برای ما نصب شده است. در صورتی که می خواهید از نصب pip مطمئن باشید باید دستور pip -V را اجرا کنید (حتما V بزرگ باشد). اگر pip برایتان نصب شده باشد دستور زیر را دریافت کنید:

pip 20.1.1 from /usr/lib/python3/dist-packages/pip (python 3.8)

از نتیجه بالا مشخص است که من از نسخه ۲۰ آن استفاده می کنم اما طبیعتا بر اساس نسخه ای از پایتون که استفاده می کنید، نسخه برگرانده شده برایتان متفاوت خواهد بود. نکته مهم اینجاست که ما از نسخه سوم زبان پایتون استفاده می کنیم. در صورتی که نتیجه به شما نشان داد که در حال استفاده از نسخه دوم هستید، به جای pip -V از pip3 -V استفاده کنید. در بعضی از سیستم عامل ها پکیج pip مخصوص نسخه دوم پایتون و pip3 مخصوص نسخه سوم آن است.

حالا برای نصب مطمئن شوید که ترمینال خود را در مسیر پروژه باز کرده اید و دستور زیر را در آن اجرا کنید:

pip install pyjokes

با انجام این کار نتیجه ای مانند نتیجه زیر را دریافت می کنید:

Collecting pyjokes

Downloading pyjokes-0.6.0-py2.py3-none-any.whl (26 kB)

Installing collected packages: pyjokes

Successfully installed pyjokes-0.6.0

بنابراین مطمئن می شویم که همه چیز به درستی نصب شده است. حالا می توانیم به پروژه خود برگردیم و از pyjokes استفاده کنیم:

import pyjokes

 

joke = pyjokes.get_joke()

 

print(joke)

تابع get_jokes از پکیج pyjokes یکی از توابعی است که یک جوک ساده را به ما می دهد. شاید بپرسید من از کجا می دانم چنین تابعی در این پکیج وجود دارد؟ در همان صفحه pypi توضیحات مربوط به پکیج ذکر شده است. من جوک تولید شده را در متغیری به نام joke ذخیره کرده و سپس آن را چاپ کرده ام. هر بار که کد بالا را اجرا کنید یک جوک متفاوت دریافت می کنید. به طور مثال من جوک زیر را دریافت کرده ام:

A programmer was found dead in the shower. Next to their body was a bottle of shampoo with the instructions 'Lather, Rinse and Repeat'.

ترجمه: یک برنامه نویس مرده را در حمام پیدا کردند. در کنار جسد او بطری شامپویی وجود داشت که در قسمت «روش مصرف» آن نوشته شده بود: با کف بشویید، آب کشی کرده و تکرار نمایید.

آیا معنی این لطیفه را متوجه شدید؟ این لطیفه به حلقه های نامتناهی اشاره می کند. اگر یادتان باشد زمانی که حلقه ها را توضیح می دادیم به شما گفتم که باید شرطی برای خروج از حلقه داشته باشیم تا در یک حلقه نامتناهی گیر نکنیم. لطیفه بالا با ذهن کامپیوتری برنامه نویسان شوخی می کند. اگر روی بطری شامپو یک حلقه مانند «شستن، آب کشی و تکرار» داشته باشیم، هیچ شرطی برای خروج از آن نداریم بنابراین این برنامه نویس آنقدر این کار را تکرار کرده که مرده است!

یک بار دیگر این کد را اجرا می کنیم تا لطیفه دیگری را دریافت کنیم:

Why are you always smiling? That's just my... regular expression.

ترجمه: چرا همیشه لبخند می زنی؟ شکل عادی من اینطوره!

در زبان انگلیسی expression چند معنی دارد که یکی از آن ها حالت چهره و صورت یک فرد است. از طرفی در برنامه نویسی regular expression یا عبارات با قاعده را داریم که الگوی یک متن را مشخص می کنند. بنابراین این لطیفه با کلمات بازی می کند تا بفهماند که الگوی صورت فرد همیشه خندان است. به همین سادگی از یک پکیج کوچک استفاده کرده ایم! پکیج های بزرگ نیز به همین شکل هستند و می توانیم با مطالعه توضیحات آن ها، تمام دستوراتشان را پیدا کرده و به کار بگیریم.

در ضمن در صورتی که می خواهید نسخه pip خود را به روز رسانی کنید باید از دستور زیر استفاده نمایید:

pip install --upgrade pip

همچنین برای مشاهده لیستی از پکیج های خودتان باید دستور pip list استفاده کنید. در نهایت برای حذف یک پکیج باید از دستور uninstall استفاده کنیم:

pip uninstall pyjokes

شما می توانید به جای pyjokes نام هر پکیج دیگری را در این قسمت قرار بدهید تا از مجموعه پکیج هایتان حذف شود. ما از دستور pip install pyjokes برای نصب این پکیج استفاده کرده ایم که به صورت خودکار آخرین نسخه پکیج را برای ما نصب می کند اما اگر بخواهیم از نسخه خاصی (قدیمی تر) استفاده کنیم باید با دو علامت = آن نسخه را مشخص کنیم:

pip install pyjokes==0.4.0

با انجام این کار نسخه 0.4.0 از این پکیج برایتان نصب می شود. چرا چنین قابلیتی وجود دارد؟ به دلیل اینکه برخی اوقات برنامه ای را می نویسیم که از نسخه خاصی از یک پکیج استفاده می کند. بعد ها این پکیج به روز رسانی شده و API آن به طور کامل تغییر می کند بنابراین کدهایی که شما قبلا نوشتید دیگر با آن سازگار نیستند. در چنین موقعیتی، دو راه پیش رو دارید:

  • پروژه را با توجه به API جدید بازنویسی کنید.
  • از نسخه ای از آن پکیج استفاده کنید که با پروژه شما سازگار است.

همچنین در برخی از مواقع چندین پروژه دارید که هر کدام از نسخه خاصی از آن پکیج استفاده می کنند. در چنین حالتی با مشکل روبرو می شویم، درست است؟ برای حل این مشکل پکیجی به نام pipenv معرفی شده است که به شما اجازه می دهد پکیج هایتان را بر اساس یک پروژه خاص نصب کنید؛ به عبارتی هر پروژه نسخه خاصی از پکیج های خودش را دارد. در صورتی که از IDE هایی مانند pyCharm استفاده کنید، یک venv یا virtual environment به صورت خودکار برای هر پروژه در نظر گرفته می شود تا بدون مشکل در آن کار کنید اما برای ویرایشگرهای دیگر باید از pipenv استفاده کنید. به طور مثال برای visual studio code می توانید به لینک زیر مراجعه کنید:

code.visualstudio.com/docs/python/environments

شاید از نظر شما استفاده از این قابلیت (جداسازی محیط های توسعه برای هر پروژه) کاری غیرضروری باشد اما اگر شروع به نوشتن پروژه های واقعی کنید حتما با این مشکل مواجه می شوید که اولا پکیج ها مکررا به روز رسانی می شوند و دوما هر پروژه نیاز به پکیج های خاصی خودش را دارد.

ماژول collections

در این قسمت می خواهیم با ماژول collections آشنا شویم که یکی از ماژول های پیش ساخته و درون هسته پایتون است:

from collections import Counter, defaultdict, OrderedDict

در کد بالا مشخص است که من از ماژول collections سه متد/کلاس Counter و defaultdict و OrderedDict را وارد کرده ام. به دلیل اینکه حرف اول Counter و OrderedDict با حروف بزرگ انگلیسی نوشته شده اند متوجه می شویم که کلاس هستند اما defaultdict فقط یک تابع است (البته در پشت صحنه همگی کلاس هستند).

بیایید با یک counter (شمارنده) شروع کنیم:

from collections import Counter, defaultdict, OrderedDict


my_list = [1, 2, 3, 4, 5, 6, 7]


print(Counter(my_list))

من لیست خود را به Counter پاس داده ام. با اجرای این کد نتیجه زیر را می گیریم:

Counter({1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1})

همانطور که می بینید این دستور یک دیکشنری را برایمان برگردانده است (در اصل یک شیء counter را ساخته است). آیا متوجه این دیکشنری می شوید؟ بگذارید لیست خود را کمی تغییر بدهیم:

from collections import Counter, defaultdict, OrderedDict


my_list = [1, 2, 3, 4, 2, 2, 5, 6, 1, 7]


print(Counter(my_list))

من این بار چند عدد تکراری را در لیست خودم قرار داده ام. حالا دوباره این کد را اجرا می کنم:

Counter({2: 3, 1: 2, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1})

همانطور که می بینید عدد ۲ در لیست ما ۳ بار تکرار شده بود بنابراین ۲ در این دیکشنری به عنوان اولین عضو آمده است. همچنین عدد یک نیز ۲ بار تکرار شده است بنابراین پس از آن آمده است و الی آخر. این تابع به ما کمک می کند که یک لیست را بدین شکل در نظر بگیریم. اگر به جای اعداد درون لیست از یک رشته استفاده کنیم چطور؟

from collections import Counter, defaultdict, OrderedDict


my_string = "Roxo is where you can learn how to code easily and joyfully"


print(Counter(my_string))

با اجرای کد بالا نتیجه زیر را دریافت می کنم:

Counter({' ': 11, 'o': 7, 'e': 5, 'y': 4, 'a': 4, 'l': 4, 'n': 3, 'i': 2, 's': 2, 'w': 2, 'h': 2, 'r': 2, 'u': 2, 'c': 2, 'd': 2, 'R': 1, 'x': 1, 't': 1, 'j': 1, 'f': 1})

همانطور که می بینید اسپیس با ۱۱ بار تکرار و حرف o با ۷ بار تکرار در مقام های اول و دوم قرار گرفته اند. مورد بعدی defaultdict است. به مثال زیر توجه کنید:

from collections import Counter, defaultdict, OrderedDict


my_dict = {

'name': 'Amir',

'age': 25

}


print(my_dict['name'])

print(my_dict['age'])

print(my_dict['HJ'])

ما در این کد یک دیکشنری ساده را داریم. من برای دسترسی به اعضای این دیکشنری از علامت های [] استفاده کرده ام. اگر به دستور print سوم توجه کنید می بینید که ما در حال دسترسی به خصوصیت به نام HJ هستیم که در دیکشنری وجود ندارد. به نظر شما با این کار چه اتفاقی می افتد؟

Amir

25

Traceback (most recent call last):

File "/mnt/Development/Roxo Academy/Python/training2/test.py", line 10, in <module>

print(my_dict['HJ'])

KeyError: 'HJ'

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

from collections import Counter, defaultdict, OrderedDict


my_dict = defaultdict(int, {

'name': 'Amir',

'age': 25

})


print(my_dict['name'])

print(my_dict['age'])

print(my_dict['HJ'])

ما باید defaultdict را صدا زده و سپس یک شیء قابل فراخوانی را به آن پاس بدهیم (یعنی شیء ای که مانند توابع قابل اجرا باشد) و به عنوان آرگومان دوم نیز همان دیکشنری خودمان را پاس می دهیم. حالا دوباره کد را اجرا می کنیم:

Amir

25

0

بنابراین از این به بعد اگر به کلیدی دسترسی پیدا کنیم که وجود نداشته باشد، عدد صفر برگردانده می شود. چرا صفر؟ در صورت عدم وجود کلید، آرگومان اول (int) فراخوانی می شود:

int()

اگر تابع بالا را به صورت عادی اجرا کنید (integer خالی) عدد صفر برایتان تولید می شود. ما می توانستیم از مقدار دیگری نیز استفاده کنیم:

from collections import Counter, defaultdict, OrderedDict


my_dict = defaultdict(list, {

'name': 'Amir',

'age': 25

})


print(my_dict['name'])

print(my_dict['age'])

print(my_dict['HJ'])

با اجرای کد بالا نتیجه زیر را می گیریم:

Amir

25

[]

حتی می توانیم خودمان تابعی را بسازیم:

from collections import Counter, defaultdict, OrderedDict




def returnNone():

return None




my_dict = defaultdict(returnNone, {

'name': 'Amir',

'age': 25

})



print(my_dict['name'])

print(my_dict['age'])

print(my_dict['HJ'])

با اجرای کد بالا نتیجه زیر را می گیریم:

Amir

25

None

به همین راحتی None برگردانده شده است. بنابراین این مسئله کاملا بر اساس تصمیم شما است که چطور آن را تنظیم کنید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری پایتون حرفه‌ای توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.